1 /*******************************************************************************
2 * Copyright (c) 2000, 2019 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.widgets;
15
16
17 import java.util.*;
18
19 import org.eclipse.swt.*;
20 import org.eclipse.swt.events.*;
21 import org.eclipse.swt.internal.*;
22 import org.eclipse.swt.internal.gtk.*;
23 import org.eclipse.swt.internal.gtk3.*;
24 import org.eclipse.swt.internal.gtk4.*;
25
26 /**
27 * This class is the abstract superclass of all user interface objects.
28 * Widgets are created, disposed and issue notification to listeners
29 * when events occur which affect them.
30 * <dl>
31 * <dt><b>Styles:</b></dt>
32 * <dd>(none)</dd>
33 * <dt><b>Events:</b></dt>
34 * <dd>Dispose</dd>
35 * </dl>
36 * <p>
37 * IMPORTANT: This class is intended to be subclassed <em>only</em>
38 * within the SWT implementation. However, it has not been marked
39 * final to allow those outside of the SWT development team to implement
40 * patched versions of the class in order to get around specific
41 * limitations in advance of when those limitations can be addressed
42 * by the team. Any class built using subclassing to access the internals
43 * of this class will likely fail to compile or run between releases and
44 * may be strongly platform specific. Subclassing should not be attempted
45 * without an intimate and detailed understanding of the workings of the
46 * hierarchy. No support is provided for user-written classes which are
47 * implemented as subclasses of this class.
48 * </p>
49 *
50 * @see #checkSubclass
51 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
52 */
53 public abstract class Widget {
54 /**
55 * the handle to the OS resource
56 * (Warning: This field is platform dependent)
57 * <p>
58 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
59 * public API. It is marked public only so that it can be shared
60 * within the packages provided by SWT. It is not available on all
61 * platforms and should never be accessed from application code.
62 * </p>
63 *
64 * @noreference This field is not intended to be referenced by clients.
65 */
66 public long handle;
67 int style, state;
68 Display display;
69 EventTable eventTable;
70 Object data;
71
72 /* Global state flags
73 *
74 * Common code pattern:
75 * & - think of AND as removing.
76 * | - think of OR as adding.
77 * state & ~flag -- Think as "removing flag"
78 * state | flag -- Think as "adding flag"
79 *
80 * state |= flag -- Flag is being added to state.
81 * state &= ~flag -- Flag is being removed from state.
82 * state & flag != 0 -- true if flag is present (think >0 = true)
83 * state & flag == 0 -- true if flag is absent (think 0 = false)
84 *
85 * (state & (flag1 | flag2)) != 0 -- true if either of the flags are present.
86 * (state & (flag1 | flag2)) == 0 -- true if both flag1 & flag2 are absent.
87 */
88 static final int DISPOSED = 1<<0;
89 static final int CANVAS = 1<<1;
90 static final int KEYED_DATA = 1<<2;
91 static final int HANDLE = 1<<3;
92 static final int DISABLED = 1<<4;
93 static final int MENU = 1<<5;
94 static final int OBSCURED = 1<<6;
95 static final int MOVED = 1<<7;
96 static final int RESIZED = 1<<8;
97 static final int ZERO_WIDTH = 1<<9;
98 static final int ZERO_HEIGHT = 1<<10;
99 static final int HIDDEN = 1<<11;
100 static final int FOREGROUND = 1<<12;
101 static final int BACKGROUND = 1<<13;
102 static final int FONT = 1<<14;
103 static final int PARENT_BACKGROUND = 1<<15;
104 static final int THEME_BACKGROUND = 1<<16;
105
106 /* A layout was requested on this widget */
107 static final int LAYOUT_NEEDED = 1<<17;
108
109 /* The preferred size of a child has changed */
110 static final int LAYOUT_CHANGED = 1<<18;
111
112 /* A layout was requested in this widget hierachy */
113 static final int LAYOUT_CHILD = 1<<19;
114
115 /* More global state flags */
116 static final int RELEASED = 1<<20;
117 static final int DISPOSE_SENT = 1<<21;
118 static final int FOREIGN_HANDLE = 1<<22;
119 static final int DRAG_DETECT = 1<<23;
120
121 /* Notify of the opportunity to skin this widget */
122 static final int SKIN_NEEDED = 1<<24;
123
124 /* Should sub-windows be checked when EnterNotify received */
125 static final int CHECK_SUBWINDOW = 1<<25;
126
127 /* Bidi "auto" text direction */
128 static final int HAS_AUTO_DIRECTION = 0;
129
130 /* Bidi flag and for auto text direction */
131 static final int AUTO_TEXT_DIRECTION = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
132
133 /* Default size for widgets */
134 static final int DEFAULT_WIDTH = 64;
135 static final int DEFAULT_HEIGHT = 64;
136
137 /* GTK signals data */
138 static final int ACTIVATE = 1;
139 static final int BUTTON_PRESS_EVENT = 2;
140 static final int BUTTON_PRESS_EVENT_INVERSE = 3;
141 static final int BUTTON_RELEASE_EVENT = 4;
142 static final int BUTTON_RELEASE_EVENT_INVERSE = 5;
143 static final int CHANGED = 6;
144 static final int CHANGE_VALUE = 7;
145 static final int CLICKED = 8;
146 static final int COMMIT = 9;
147 static final int CONFIGURE_EVENT = 10;
148 static final int DELETE_EVENT = 11;
149 static final int DELETE_RANGE = 12;
150 static final int DELETE_TEXT = 13;
151 static final int ENTER_NOTIFY_EVENT = 14;
152 static final int EVENT = 15;
153 static final int EVENT_AFTER = 16;
154 static final int EXPAND_COLLAPSE_CURSOR_ROW = 17;
155 static final int EXPOSE_EVENT = 18;
156 static final int DRAW = EXPOSE_EVENT;
157 static final int EXPOSE_EVENT_INVERSE = 19;
158 static final int FOCUS = 20;
159 static final int FOCUS_IN_EVENT = 21;
160 static final int FOCUS_OUT_EVENT = 22;
161 static final int GRAB_FOCUS = 23;
162 static final int HIDE = 24;
163 static final int INPUT = 25;
164 static final int INSERT_TEXT = 26;
165 static final int KEY_PRESS_EVENT = 27;
166 static final int KEY_RELEASE_EVENT = 28;
167 static final int LEAVE_NOTIFY_EVENT = 29;
168 static final int MAP = 30;
169 static final int MAP_EVENT = 31;
170 static final int MNEMONIC_ACTIVATE = 32;
171 static final int MOTION_NOTIFY_EVENT = 33;
172 static final int MOTION_NOTIFY_EVENT_INVERSE = 34;
173 static final int MOVE_FOCUS = 35;
174 static final int OUTPUT = 36;
175 static final int POPULATE_POPUP = 37;
176 static final int POPUP_MENU = 38;
177 static final int PREEDIT_CHANGED = 39;
178 static final int REALIZE = 40;
179 static final int ROW_ACTIVATED = 41;
180 static final int SCROLL_CHILD = 42;
181 static final int SCROLL_EVENT = 43;
182 static final int SELECT = 44;
183 static final int SHOW = 45;
184 static final int SHOW_HELP = 46;
185 static final int SIZE_ALLOCATE = 47;
186 static final int STYLE_UPDATED = 48;
187 static final int SWITCH_PAGE = 49;
188 static final int TEST_COLLAPSE_ROW = 50;
189 static final int TEST_EXPAND_ROW = 51;
190 static final int TEXT_BUFFER_INSERT_TEXT = 52;
191 static final int TOGGLED = 53;
192 static final int UNMAP = 54;
193 static final int UNMAP_EVENT = 55;
194 static final int UNREALIZE = 56;
195 static final int VALUE_CHANGED = 57;
196 static final int WINDOW_STATE_EVENT = 59;
197 static final int ACTIVATE_INVERSE = 60;
198 static final int DAY_SELECTED = 61;
199 static final int MONTH_CHANGED = 62;
200 static final int STATUS_ICON_POPUP_MENU = 63;
201 static final int ROW_INSERTED = 64;
202 static final int ROW_DELETED = 65;
203 static final int DAY_SELECTED_DOUBLE_CLICK = 66;
204 static final int ICON_RELEASE = 67;
205 static final int SELECTION_DONE = 68;
206 static final int START_INTERACTIVE_SEARCH = 69;
207 static final int BACKSPACE = 70;
208 static final int BACKSPACE_INVERSE = 71;
209 static final int COPY_CLIPBOARD = 72;
210 static final int COPY_CLIPBOARD_INVERSE = 73;
211 static final int CUT_CLIPBOARD = 74;
212 static final int CUT_CLIPBOARD_INVERSE = 75;
213 static final int PASTE_CLIPBOARD = 76;
214 static final int PASTE_CLIPBOARD_INVERSE = 77;
215 static final int DELETE_FROM_CURSOR = 78;
216 static final int DELETE_FROM_CURSOR_INVERSE = 79;
217 static final int MOVE_CURSOR = 80;
218 static final int MOVE_CURSOR_INVERSE = 81;
219 static final int DIRECTION_CHANGED = 82;
220 static final int CREATE_MENU_PROXY = 83;
221 static final int ROW_HAS_CHILD_TOGGLED = 84;
222 static final int POPPED_UP = 85;
223 static final int FOCUS_IN = 86;
224 static final int FOCUS_OUT = 87;
225 static final int IM_UPDATE = 88;
226 static final int KEY_PRESSED = 89;
227 static final int KEY_RELEASED = 90;
228 static final int DECELERATE = 91;
229 static final int SCROLL = 92;
230 static final int SCROLL_BEGIN = 93;
231 static final int SCROLL_END = 94;
232 static final int ENTER = 95;
233 static final int LEAVE = 96;
234 static final int MOTION = 97;
235 static final int MOTION_INVERSE = 98;
236 static final int CLOSE_REQUEST = 99;
237 static final int GESTURE_PRESSED = 100;
238 static final int GESTURE_RELEASED = 101;
239 static final int NOTIFY_STATE = 102;
240 static final int SIZE_ALLOCATE_GTK4 = 103;
241 static final int DPI_CHANGED = 104;
242 static final int LAST_SIGNAL = 105;
243
244 static final String IS_ACTIVE = "org.eclipse.swt.internal.control.isactive"; //$NON-NLS-1$
245 static final String KEY_CHECK_SUBWINDOW = "org.eclipse.swt.internal.control.checksubwindow"; //$NON-NLS-1$
246 static final String KEY_GTK_CSS = "org.eclipse.swt.internal.gtk.css"; //$NON-NLS-1$
247
248 static Callback gdkSeatGrabPrepareFunc;
249
250 /**
251 * Prevents uninitialized instances from being created outside the package.
252 */
Widget()253 Widget () {}
254
255 /**
256 * Constructs a new instance of this class given its parent
257 * and a style value describing its behavior and appearance.
258 * <p>
259 * The style value is either one of the style constants defined in
260 * class <code>SWT</code> which is applicable to instances of this
261 * class, or must be built by <em>bitwise OR</em>'ing together
262 * (that is, using the <code>int</code> "|" operator) two or more
263 * of those <code>SWT</code> style constants. The class description
264 * lists the style constants that are applicable to the class.
265 * Style bits are also inherited from superclasses.
266 * </p>
267 *
268 * @param parent a widget which will be the parent of the new instance (cannot be null)
269 * @param style the style of widget to construct
270 *
271 * @exception IllegalArgumentException <ul>
272 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
273 * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
274 * </ul>
275 * @exception SWTException <ul>
276 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
277 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
278 * </ul>
279 *
280 * @see SWT
281 * @see #checkSubclass
282 * @see #getStyle
283 */
Widget(Widget parent, int style)284 public Widget (Widget parent, int style) {
285 checkSubclass ();
286 checkParent (parent);
287 this.style = style;
288 display = parent.display;
289 reskinWidget ();
290 }
291
_addListener(int eventType, Listener listener)292 void _addListener (int eventType, Listener listener) {
293 if (eventTable == null) eventTable = new EventTable ();
294 eventTable.hook (eventType, listener);
295 }
296
297 /**
298 * Adds the listener to the collection of listeners who will
299 * be notified when an event of the given type occurs. When the
300 * event does occur in the widget, the listener is notified by
301 * sending it the <code>handleEvent()</code> message. The event
302 * type is one of the event constants defined in class <code>SWT</code>.
303 *
304 * @param eventType the type of event to listen for
305 * @param listener the listener which should be notified when the event occurs
306 *
307 * @exception IllegalArgumentException <ul>
308 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
309 * </ul>
310 * @exception SWTException <ul>
311 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
312 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
313 * </ul>
314 *
315 * @see Listener
316 * @see SWT
317 * @see #getListeners(int)
318 * @see #removeListener(int, Listener)
319 * @see #notifyListeners
320 */
addListener(int eventType, Listener listener)321 public void addListener (int eventType, Listener listener) {
322 checkWidget ();
323 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
324 _addListener (eventType, listener);
325 }
326
327 /**
328 * Adds the listener to the collection of listeners who will
329 * be notified when the widget is disposed. When the widget is
330 * disposed, the listener is notified by sending it the
331 * <code>widgetDisposed()</code> message.
332 *
333 * @param listener the listener which should be notified when the receiver is disposed
334 *
335 * @exception IllegalArgumentException <ul>
336 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
337 * </ul>
338 * @exception SWTException <ul>
339 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
340 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
341 * </ul>
342 *
343 * @see DisposeListener
344 * @see #removeDisposeListener
345 */
addDisposeListener(DisposeListener listener)346 public void addDisposeListener (DisposeListener listener) {
347 checkWidget ();
348 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
349 TypedListener typedListener = new TypedListener (listener);
350 addListener (SWT.Dispose, typedListener);
351 }
352
paintWindow()353 long paintWindow () {
354 return 0;
355 }
356
paintSurface()357 long paintSurface () {
358 return 0;
359 }
360
cssHandle()361 long cssHandle() {
362 return handle;
363 }
364
checkBits(int style, int int0, int int1, int int2, int int3, int int4, int int5)365 static int checkBits (int style, int int0, int int1, int int2, int int3, int int4, int int5) {
366 int mask = int0 | int1 | int2 | int3 | int4 | int5;
367 if ((style & mask) == 0) style |= int0;
368 if ((style & int0) != 0) style = (style & ~mask) | int0;
369 if ((style & int1) != 0) style = (style & ~mask) | int1;
370 if ((style & int2) != 0) style = (style & ~mask) | int2;
371 if ((style & int3) != 0) style = (style & ~mask) | int3;
372 if ((style & int4) != 0) style = (style & ~mask) | int4;
373 if ((style & int5) != 0) style = (style & ~mask) | int5;
374 return style;
375 }
376
cellDataProc(long tree_column, long cell, long tree_model, long iter, long data)377 long cellDataProc (long tree_column, long cell, long tree_model, long iter, long data) {
378 return 0;
379 }
380
checkOpen()381 void checkOpen () {
382 /* Do nothing */
383 }
384
checkOrientation(Widget parent)385 void checkOrientation (Widget parent) {
386 style &= ~SWT.MIRRORED;
387 if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) == 0) {
388 if (parent != null) {
389 if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) style |= SWT.LEFT_TO_RIGHT;
390 if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) style |= SWT.RIGHT_TO_LEFT;
391 }
392 }
393 style = checkBits (style, SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, 0, 0, 0, 0);
394 }
395
396 /**
397 * Throws an exception if the specified widget can not be
398 * used as a parent for the receiver.
399 *
400 * @exception IllegalArgumentException <ul>
401 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
402 * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
403 * </ul>
404 * @exception SWTException <ul>
405 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
406 * </ul>
407 */
checkParent(Widget parent)408 void checkParent (Widget parent) {
409 if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
410 if (parent.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
411 parent.checkWidget ();
412 parent.checkOpen ();
413 }
414
415 /**
416 * Checks that this class can be subclassed.
417 * <p>
418 * The SWT class library is intended to be subclassed
419 * only at specific, controlled points (most notably,
420 * <code>Composite</code> and <code>Canvas</code> when
421 * implementing new widgets). This method enforces this
422 * rule unless it is overridden.
423 * </p><p>
424 * <em>IMPORTANT:</em> By providing an implementation of this
425 * method that allows a subclass of a class which does not
426 * normally allow subclassing to be created, the implementer
427 * agrees to be fully responsible for the fact that any such
428 * subclass will likely fail between SWT releases and will be
429 * strongly platform specific. No support is provided for
430 * user-written classes which are implemented in this fashion.
431 * </p><p>
432 * The ability to subclass outside of the allowed SWT classes
433 * is intended purely to enable those not on the SWT development
434 * team to implement patches in order to get around specific
435 * limitations in advance of when those limitations can be
436 * addressed by the team. Subclassing should not be attempted
437 * without an intimate and detailed understanding of the hierarchy.
438 * </p>
439 *
440 * @exception SWTException <ul>
441 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
442 * </ul>
443 */
checkSubclass()444 protected void checkSubclass () {
445 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
446 }
447
448 /**
449 * Throws an <code>SWTException</code> if the receiver can not
450 * be accessed by the caller. This may include both checks on
451 * the state of the receiver and more generally on the entire
452 * execution context. This method <em>should</em> be called by
453 * widget implementors to enforce the standard SWT invariants.
454 * <p>
455 * Currently, it is an error to invoke any method (other than
456 * <code>isDisposed()</code>) on a widget that has had its
457 * <code>dispose()</code> method called. It is also an error
458 * to call widget methods from any thread that is different
459 * from the thread that created the widget.
460 * </p><p>
461 * In future releases of SWT, there may be more or fewer error
462 * checks and exceptions may be thrown for different reasons.
463 * </p>
464 *
465 * @exception SWTException <ul>
466 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
467 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
468 * </ul>
469 */
checkWidget()470 protected void checkWidget () {
471 Display display = this.display;
472 if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);
473 if (display.thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
474 if ((state & DISPOSED) != 0) error (SWT.ERROR_WIDGET_DISPOSED);
475 }
476
createHandle(int index)477 void createHandle (int index) {
478 }
479
createWidget(int index)480 void createWidget (int index) {
481 createHandle (index);
482 setOrientation (true);
483 hookEvents ();
484 register ();
485 }
486
deregister()487 void deregister () {
488 if (handle == 0) return;
489 if ((state & HANDLE) != 0) display.removeWidget (handle);
490 }
491
destroyWidget()492 void destroyWidget () {
493 long topHandle = topHandle ();
494 releaseHandle ();
495 if (topHandle != 0 && (state & HANDLE) != 0) {
496 if (GTK.GTK4) {
497 GTK.gtk_widget_unparent(topHandle);
498 } else {
499 GTK3.gtk_widget_destroy(topHandle);
500 }
501 }
502 }
503
504 /**
505 * Disposes of the operating system resources associated with
506 * the receiver and all its descendants. After this method has
507 * been invoked, the receiver and all descendants will answer
508 * <code>true</code> when sent the message <code>isDisposed()</code>.
509 * Any internal connections between the widgets in the tree will
510 * have been removed to facilitate garbage collection.
511 * This method does nothing if the widget is already disposed.
512 * <p>
513 * NOTE: This method is not called recursively on the descendants
514 * of the receiver. This means that, widget implementers can not
515 * detect when a widget is being disposed of by re-implementing
516 * this method, but should instead listen for the <code>Dispose</code>
517 * event.
518 * </p>
519 *
520 * @exception SWTException <ul>
521 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
522 * </ul>
523 *
524 * @see #addDisposeListener
525 * @see #removeDisposeListener
526 * @see #checkWidget
527 */
dispose()528 public void dispose () {
529 /*
530 * Note: It is valid to attempt to dispose a widget
531 * more than once. If this happens, fail silently.
532 */
533 if (isDisposed ()) return;
534 if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
535 release (true);
536 }
537
dpiChanged(long object, long arg0)538 long dpiChanged (long object, long arg0) {
539 int oldScaleFactor = DPIUtil.getDeviceZoom() / 100;
540 int newScaleFactor = GTK.gtk_widget_get_scale_factor(object);
541
542 if (oldScaleFactor != newScaleFactor) {
543 display.dpiChanged(newScaleFactor);
544
545 Event event = new Event();
546 event.type = SWT.ZoomChanged;
547 event.widget = this;
548 event.detail = newScaleFactor;
549 event.doit = true;
550 notifyListeners(SWT.ZoomChanged, event);
551 }
552
553 return 0;
554 }
555
error(int code)556 void error (int code) {
557 SWT.error (code);
558 }
559
560 /**
561 * Returns the application defined widget data associated
562 * with the receiver, or null if it has not been set. The
563 * <em>widget data</em> is a single, unnamed field that is
564 * stored with every widget.
565 * <p>
566 * Applications may put arbitrary objects in this field. If
567 * the object stored in the widget data needs to be notified
568 * when the widget is disposed of, it is the application's
569 * responsibility to hook the Dispose event on the widget and
570 * do so.
571 * </p>
572 *
573 * @return the widget data
574 *
575 * @exception SWTException <ul>
576 * <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li>
577 * <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li>
578 * </ul>
579 *
580 * @see #setData(Object)
581 */
getData()582 public Object getData () {
583 checkWidget();
584 return (state & KEYED_DATA) != 0 ? ((Object []) data) [0] : data;
585 }
586 /**
587 * Returns the application defined property of the receiver
588 * with the specified name, or null if it has not been set.
589 * <p>
590 * Applications may have associated arbitrary objects with the
591 * receiver in this fashion. If the objects stored in the
592 * properties need to be notified when the widget is disposed
593 * of, it is the application's responsibility to hook the
594 * Dispose event on the widget and do so.
595 * </p>
596 *
597 * @param key the name of the property
598 * @return the value of the property or null if it has not been set
599 *
600 * @exception IllegalArgumentException <ul>
601 * <li>ERROR_NULL_ARGUMENT - if the key is null</li>
602 * </ul>
603 * @exception SWTException <ul>
604 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
605 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
606 * </ul>
607 *
608 * @see #setData(String, Object)
609 */
getData(String key)610 public Object getData (String key) {
611 checkWidget();
612 if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
613 if (key.equals (KEY_CHECK_SUBWINDOW)) {
614 return (state & CHECK_SUBWINDOW) != 0;
615 }
616 if (key.equals(IS_ACTIVE)) return isActive ();
617 if ((state & KEYED_DATA) != 0) {
618 Object [] table = (Object []) data;
619 for (int i=1; i<table.length; i+=2) {
620 if (key.equals (table [i])) return table [i+1];
621 }
622 }
623 return null;
624 }
625
626 /**
627 * Returns the <code>Display</code> that is associated with
628 * the receiver.
629 * <p>
630 * A widget's display is either provided when it is created
631 * (for example, top level <code>Shell</code>s) or is the
632 * same as its parent's display.
633 * </p>
634 *
635 * @return the receiver's display
636 *
637 * @exception SWTException <ul>
638 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
639 * </ul>
640 */
getDisplay()641 public Display getDisplay () {
642 Display display = this.display;
643 if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);
644 return display;
645 }
646
647 /**
648 * Returns an array of listeners who will be notified when an event
649 * of the given type occurs. The event type is one of the event constants
650 * defined in class <code>SWT</code>.
651 *
652 * @param eventType the type of event to listen for
653 * @return an array of listeners that will be notified when the event occurs
654 *
655 * @exception SWTException <ul>
656 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
657 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
658 * </ul>
659 *
660 * @see Listener
661 * @see SWT
662 * @see #addListener(int, Listener)
663 * @see #removeListener(int, Listener)
664 * @see #notifyListeners
665 *
666 * @since 3.4
667 */
getListeners(int eventType)668 public Listener[] getListeners (int eventType) {
669 checkWidget();
670 if (eventTable == null) return new Listener[0];
671 return eventTable.getListeners(eventType);
672 }
673
getName()674 String getName () {
675 // String string = getClass ().getName ();
676 // int index = string.lastIndexOf ('.');
677 // if (index == -1) return string;
678 String string = getClass ().getName ();
679 int index = string.length ();
680 while ((--index > 0) && (string.charAt (index) != '.')) {}
681 return string.substring (index + 1, string.length ());
682 }
683
getNameText()684 String getNameText () {
685 return "";
686 }
687
688 /**
689 * Returns the receiver's style information.
690 * <p>
691 * Note that the value which is returned by this method <em>may
692 * not match</em> the value which was provided to the constructor
693 * when the receiver was created. This can occur when the underlying
694 * operating system does not support a particular combination of
695 * requested styles. For example, if the platform widget used to
696 * implement a particular SWT widget always has scroll bars, the
697 * result of calling this method would always have the
698 * <code>SWT.H_SCROLL</code> and <code>SWT.V_SCROLL</code> bits set.
699 * </p>
700 *
701 * @return the style bits
702 *
703 * @exception SWTException <ul>
704 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
705 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
706 * </ul>
707 */
getStyle()708 public int getStyle () {
709 checkWidget ();
710 return style;
711 }
712
713
gtk_activate(long widget)714 long gtk_activate (long widget) {
715 return 0;
716 }
717
gtk_adjustment_get(long adjustmentHandle, GtkAdjustment adjustment)718 void gtk_adjustment_get(long adjustmentHandle, GtkAdjustment adjustment) {
719 adjustment.lower = GTK.gtk_adjustment_get_lower(adjustmentHandle);
720 adjustment.upper = GTK.gtk_adjustment_get_upper(adjustmentHandle);
721 adjustment.page_increment = GTK.gtk_adjustment_get_page_increment(adjustmentHandle);
722 adjustment.step_increment = GTK.gtk_adjustment_get_step_increment(adjustmentHandle);
723 adjustment.page_size = GTK.gtk_adjustment_get_page_size(adjustmentHandle);
724 adjustment.value = GTK.gtk_adjustment_get_value(adjustmentHandle);
725 }
726
gtk_button_press_event(long widget, long event)727 long gtk_button_press_event (long widget, long event) {
728 return 0;
729 }
730
gtk_button_release_event(long widget, long event)731 long gtk_button_release_event (long widget, long event) {
732 return 0;
733 }
734
gtk_gesture_press_event(long gesture, int n_press, double x, double y, long event)735 void gtk_gesture_press_event (long gesture, int n_press, double x, double y, long event) {
736 }
737
gtk_gesture_release_event(long gesture, int n_press, double x, double y, long event)738 void gtk_gesture_release_event (long gesture, int n_press, double x, double y, long event) {
739 }
740
gtk_changed(long widget)741 long gtk_changed (long widget) {
742 return 0;
743 }
744
gtk_change_value(long widget, int scroll, double value, long user_data)745 boolean gtk_change_value (long widget, int scroll, double value, long user_data) {
746 return false;
747 }
748
gtk_clicked(long widget)749 long gtk_clicked (long widget) {
750 return 0;
751 }
752
gtk_close_request(long widget)753 long gtk_close_request (long widget) {
754 return 0;
755 }
756
gtk_commit(long imcontext, long text)757 long gtk_commit (long imcontext, long text) {
758 return 0;
759 }
760
gtk_configure_event(long widget, long event)761 long gtk_configure_event (long widget, long event) {
762 return 0;
763 }
764
gtk_create_menu_proxy(long widget)765 long gtk_create_menu_proxy (long widget) {
766 return 0;
767 }
768
gtk_day_selected(long widget)769 long gtk_day_selected (long widget) {
770 return 0;
771 }
772
gtk_day_selected_double_click(long widget)773 long gtk_day_selected_double_click (long widget) {
774 return 0;
775 }
776
gtk_delete_event(long widget, long event)777 long gtk_delete_event (long widget, long event) {
778 return 0;
779 }
780
gtk_delete_range(long widget, long iter1, long iter2)781 long gtk_delete_range (long widget, long iter1, long iter2) {
782 return 0;
783 }
784
gtk_delete_text(long widget, long start_pos, long end_pos)785 long gtk_delete_text (long widget, long start_pos, long end_pos) {
786 return 0;
787 }
788
gtk_enter_notify_event(long widget, long event)789 long gtk_enter_notify_event (long widget, long event) {
790 return 0;
791 }
792
gtk_event_after(long widget, long event)793 long gtk_event_after (long widget, long event) {
794 return 0;
795 }
796
gtk_expand_collapse_cursor_row(long widget, long logical, long expand, long open_all)797 long gtk_expand_collapse_cursor_row (long widget, long logical, long expand, long open_all) {
798 return 0;
799 }
800
gtk_draw(long widget, long cairo)801 long gtk_draw (long widget, long cairo) {
802 return 0;
803 }
804
gtk_focus(long widget, long event)805 long gtk_focus (long widget, long event) {
806 return 0;
807 }
808
gtk_focus_in_event(long widget, long event)809 long gtk_focus_in_event (long widget, long event) {
810 return 0;
811 }
812
gtk_focus_out_event(long widget, long event)813 long gtk_focus_out_event (long widget, long event) {
814 return 0;
815 }
816
gtk_grab_focus(long widget)817 long gtk_grab_focus (long widget) {
818 return 0;
819 }
820
gtk_hide(long widget)821 long gtk_hide (long widget) {
822 return 0;
823 }
824
gtk_icon_release(long widget, long icon_pos, long event)825 long gtk_icon_release (long widget, long icon_pos, long event) {
826 return 0;
827 }
828
gtk_input(long widget, long arg1)829 long gtk_input (long widget, long arg1) {
830 return 0;
831 }
832
gtk_insert_text(long widget, long new_text, long new_text_length, long position)833 long gtk_insert_text (long widget, long new_text, long new_text_length, long position) {
834 return 0;
835 }
836
gtk_key_press_event(long widget, long event)837 long gtk_key_press_event (long widget, long event) {
838 return sendKeyEvent (SWT.KeyDown, event) ? 0 : 1;
839 }
840
gtk_key_release_event(long widget, long event)841 long gtk_key_release_event (long widget, long event) {
842 return sendKeyEvent (SWT.KeyUp, event) ? 0 : 1;
843 }
844
gtk_leave_notify_event(long widget, long event)845 long gtk_leave_notify_event (long widget, long event) {
846 return 0;
847 }
848
gtk_map(long widget)849 long gtk_map (long widget) {
850 return 0;
851 }
852
gtk_map_event(long widget, long event)853 long gtk_map_event (long widget, long event) {
854 return 0;
855 }
856
857 /**
858 * <p>GTK3.22+ has API which allows clients of GTK to connect a menu to the "popped-up" signal.
859 * This callback is triggered after the menu is popped up/shown to the user, and provides
860 * information about the actual position and size of the menu, as shown to the user.</p>
861 *
862 * <p>SWT clients can enable this functionality by launching their application with the
863 * SWT_MENU_LOCATION_DEBUGGING environment variable set to 1. If enabled, the previously mentioned
864 * positioning and size information will be printed to the console. The information comes from GTK
865 * internals and is stored in the method parameters.</p>
866 *
867 * @param widget the memory address of the menu which was popped up
868 * @param flipped_rect a pointer to the GdkRectangle containing the flipped location and size of the menu
869 * @param final_rect a pointer to the GdkRectangle containing the final (after all internal adjustments)
870 * location and size of the menu
871 * @param flipped_x a boolean flag indicating whether the menu has been inverted along the X-axis
872 * @param flipped_y a boolean flag indicating whether the menu has been inverted along the Y-axis
873 */
gtk_menu_popped_up(long widget, long flipped_rect, long final_rect, long flipped_x, long flipped_y)874 long gtk_menu_popped_up (long widget, long flipped_rect, long final_rect, long flipped_x, long flipped_y) {
875 return 0;
876 }
877
gtk_mnemonic_activate(long widget, long arg1)878 long gtk_mnemonic_activate (long widget, long arg1) {
879 return 0;
880 }
881
gtk_month_changed(long widget)882 long gtk_month_changed (long widget) {
883 return 0;
884 }
885
gtk_motion_notify_event(long widget, long event)886 long gtk_motion_notify_event (long widget, long event) {
887 return 0;
888 }
889
gtk_move_focus(long widget, long event)890 long gtk_move_focus (long widget, long event) {
891 return 0;
892 }
893
gtk_output(long widget)894 long gtk_output (long widget) {
895 return 0;
896 }
897
gtk_populate_popup(long widget, long menu)898 long gtk_populate_popup (long widget, long menu) {
899 return 0;
900 }
901
gtk_popup_menu(long widget)902 long gtk_popup_menu (long widget) {
903 return 0;
904 }
905
gtk_preedit_changed(long imcontext)906 long gtk_preedit_changed (long imcontext) {
907 return 0;
908 }
909
gtk_realize(long widget)910 long gtk_realize (long widget) {
911 return 0;
912 }
913
gtk_row_activated(long tree, long path, long column)914 long gtk_row_activated (long tree, long path, long column) {
915 return 0;
916 // Note on SWT Tree/Table/List. This signal is no longer used for sending events, instead
917 // Send DefaultSelection is manually emitted. We use this function to know whether a
918 // 'row-activated' is triggered. See Bug 312568, 518414.
919 }
920
gtk_row_deleted(long model, long path)921 long gtk_row_deleted (long model, long path) {
922 return 0;
923 }
924
gtk_row_inserted(long model, long path, long iter)925 long gtk_row_inserted (long model, long path, long iter) {
926 return 0;
927 }
928
gtk_row_has_child_toggled(long model, long path, long iter)929 long gtk_row_has_child_toggled (long model, long path, long iter) {
930 return 0;
931 }
932
gtk_scroll_child(long widget, long scrollType, long horizontal)933 long gtk_scroll_child (long widget, long scrollType, long horizontal) {
934 return 0;
935 }
936
gtk_scroll_event(long widget, long event)937 long gtk_scroll_event (long widget, long event) {
938 return 0;
939 }
940
gtk_select(long item)941 long gtk_select (long item) {
942 return 0;
943 }
944
gtk_selection_done(long menushell)945 long gtk_selection_done (long menushell) {
946 return 0;
947 }
948
gtk_show(long widget)949 long gtk_show (long widget) {
950 return 0;
951 }
952
gtk_show_help(long widget, long helpType)953 long gtk_show_help (long widget, long helpType) {
954 return 0;
955 }
956
gtk_size_allocate(long widget, long allocation)957 long gtk_size_allocate (long widget, long allocation) {
958 return 0;
959 }
960
gtk_status_icon_popup_menu(long handle, long button, long activate_time)961 long gtk_status_icon_popup_menu (long handle, long button, long activate_time) {
962 return 0;
963 }
964
gtk_start_interactive_search(long widget)965 long gtk_start_interactive_search (long widget) {
966 return 0;
967 }
968
gtk_style_updated(long widget)969 long gtk_style_updated (long widget) {
970 return 0;
971 }
972
gtk_switch_page(long notebook, long page, int page_num)973 long gtk_switch_page (long notebook, long page, int page_num) {
974 return 0;
975 }
976
gtk_test_collapse_row(long tree, long iter, long path)977 long gtk_test_collapse_row (long tree, long iter, long path) {
978 return 0;
979 }
980
gtk_test_expand_row(long tree, long iter, long path)981 long gtk_test_expand_row (long tree, long iter, long path) {
982 return 0;
983 }
984
gtk_text_buffer_insert_text(long widget, long iter, long text, long length)985 long gtk_text_buffer_insert_text (long widget, long iter, long text, long length) {
986 return 0;
987 }
988
gtk_timer()989 long gtk_timer () {
990 return 0;
991 }
992
gtk_toggled(long renderer, long pathStr)993 long gtk_toggled (long renderer, long pathStr) {
994 return 0;
995 }
996
997 /*
998 * Bug 498165: gtk_tree_view_column_cell_get_position() sets off rendererGetPreferredWidthCallback in GTK3 which is an issue
999 * if there is an ongoing MeasureEvent listener. Disabling it and re-enabling the callback after the method is called
1000 * prevents a stack overflow from occurring.
1001 */
gtk_tree_view_column_cell_get_position(long column, long cell_renderer, int[] start_pos, int[] width)1002 boolean gtk_tree_view_column_cell_get_position (long column, long cell_renderer, int[] start_pos, int[] width) {
1003 Callback.setEnabled(false);
1004 boolean result = GTK.gtk_tree_view_column_cell_get_position (column, cell_renderer, start_pos, width);
1005 Callback.setEnabled(true);
1006 return result;
1007 }
1008
gtk_unmap(long widget)1009 long gtk_unmap (long widget) {
1010 return 0;
1011 }
1012
gtk_unmap_event(long widget, long event)1013 long gtk_unmap_event (long widget, long event) {
1014 return 0;
1015 }
1016
gtk_unrealize(long widget)1017 long gtk_unrealize (long widget) {
1018 return 0;
1019 }
1020
gtk_value_changed(long range)1021 long gtk_value_changed(long range) {
1022 return 0;
1023 }
1024
gtk_window_state_event(long widget, long event)1025 long gtk_window_state_event (long widget, long event) {
1026 return 0;
1027 }
1028
fontHeight(long font, long widgetHandle)1029 int fontHeight (long font, long widgetHandle) {
1030 long context = GTK.gtk_widget_get_pango_context (widgetHandle);
1031 long lang = OS.pango_context_get_language (context);
1032 long metrics = OS.pango_context_get_metrics (context, font, lang);
1033 int ascent = OS.pango_font_metrics_get_ascent (metrics);
1034 int descent = OS.pango_font_metrics_get_descent (metrics);
1035 OS.pango_font_metrics_unref (metrics);
1036 return OS.PANGO_PIXELS (ascent + descent);
1037 }
1038
filterProc(long xEvent, long gdkEvent, long data2)1039 long filterProc(long xEvent, long gdkEvent, long data2) {
1040 return 0;
1041 }
1042
filters(int eventType)1043 boolean filters (int eventType) {
1044 return display.filters (eventType);
1045 }
1046
fixMnemonic(String string)1047 char [] fixMnemonic (String string) {
1048 return fixMnemonic (string, true);
1049 }
1050
fixMnemonic(String string, boolean replace)1051 char [] fixMnemonic (String string, boolean replace) {
1052 return fixMnemonic (string, replace, false);
1053 }
1054
fixMnemonic(String string, boolean replace, boolean removeAppended)1055 char [] fixMnemonic (String string, boolean replace, boolean removeAppended) {
1056 int length = string.length ();
1057 char [] text = new char [length];
1058 string.getChars (0, length, text, 0);
1059 int i = 0, j = 0;
1060 char [] result = new char [length * 2];
1061 while (i < length) {
1062 switch (text [i]) {
1063 case '&':
1064 if (i + 1 < length && text [i + 1] == '&') {
1065 result [j++] = text [i++];
1066 } else {
1067 if (replace) result [j++] = '_';
1068 }
1069 i++;
1070 break;
1071 /*
1072 * In Japanese like languages where mnemonics are not taken from the
1073 * source label text but appended in parentheses like "(&M)" at end. In order to
1074 * allow the reuse of such label text as a tool-tip text as well, "(&M)" like
1075 * character sequence has to be removed from the end of CJK-style mnemonics.
1076 */
1077 case '(':
1078 if (removeAppended && i + 4 == string.length () && text [i + 1] == '&' && text [i + 3] == ')') {
1079 if (replace) result [j++] = ' ';
1080 i += 4;
1081 break; // break switch case only if we are removing the mnemonic
1082 }
1083 else {
1084 // otherwise fall through (default case applies)
1085 result [j++] = text [i++];
1086 break;
1087 }
1088 case '_':
1089 if (replace) result [j++] = '_';
1090 //FALL THROUGH
1091 default:
1092 result [j++] = text [i++];
1093 }
1094 }
1095 return result;
1096 }
1097
isActive()1098 boolean isActive () {
1099 return true;
1100 }
1101
1102 /**
1103 * Returns <code>true</code> if the widget has auto text direction,
1104 * and <code>false</code> otherwise.
1105 *
1106 * @return <code>true</code> when the widget has auto direction and <code>false</code> otherwise
1107 *
1108 * @see SWT#AUTO_TEXT_DIRECTION
1109 *
1110 * @since 3.105
1111 */
isAutoDirection()1112 public boolean isAutoDirection () {
1113 return false;
1114 }
1115
1116 /**
1117 * Returns <code>true</code> if the widget has been disposed,
1118 * and <code>false</code> otherwise.
1119 * <p>
1120 * This method gets the dispose state for the widget.
1121 * When a widget has been disposed, it is an error to
1122 * invoke any other method (except {@link #dispose()}) using the widget.
1123 * </p>
1124 *
1125 * @return <code>true</code> when the widget is disposed and <code>false</code> otherwise
1126 */
isDisposed()1127 public boolean isDisposed () {
1128 return (state & DISPOSED) != 0;
1129 }
1130
1131 /**
1132 * Returns <code>true</code> if there are any listeners
1133 * for the specified event type associated with the receiver,
1134 * and <code>false</code> otherwise. The event type is one of
1135 * the event constants defined in class <code>SWT</code>.
1136 *
1137 * @param eventType the type of event
1138 * @return true if the event is hooked
1139 *
1140 * @exception SWTException <ul>
1141 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1142 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1143 * </ul>
1144 *
1145 * @see SWT
1146 */
isListening(int eventType)1147 public boolean isListening (int eventType) {
1148 checkWidget ();
1149 return hooks (eventType);
1150 }
1151
isValidThread()1152 boolean isValidThread () {
1153 return getDisplay ().isValidThread ();
1154 }
1155
isValidSubclass()1156 boolean isValidSubclass() {
1157 return Display.isValidClass(getClass());
1158 }
1159
hookEvents()1160 void hookEvents () {
1161 if (handle != 0) {
1162 OS.g_signal_connect (handle, OS.dpi_changed, display.notifyProc, Widget.DPI_CHANGED);
1163 }
1164 }
1165
1166 /*
1167 * Returns <code>true</code> if the specified eventType is
1168 * hooked, and <code>false</code> otherwise. Implementations
1169 * of SWT can avoid creating objects and sending events
1170 * when an event happens in the operating system but
1171 * there are no listeners hooked for the event.
1172 *
1173 * @param eventType the event to be checked
1174 *
1175 * @return <code>true</code> when the eventType is hooked and <code>false</code> otherwise
1176 *
1177 * @see #isListening
1178 */
hooks(int eventType)1179 boolean hooks (int eventType) {
1180 if (eventTable == null) return false;
1181 return eventTable.hooks (eventType);
1182 }
1183
hoverProc(long widget)1184 long hoverProc (long widget) {
1185 return 0;
1186 }
1187
mnemonicHit(long mnemonicHandle, char key)1188 boolean mnemonicHit (long mnemonicHandle, char key) {
1189 if (!mnemonicMatch (mnemonicHandle, key)) return false;
1190 OS.g_signal_handlers_block_matched (mnemonicHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, MNEMONIC_ACTIVATE);
1191 boolean result = GTK.gtk_widget_mnemonic_activate (mnemonicHandle, false);
1192 OS.g_signal_handlers_unblock_matched (mnemonicHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, MNEMONIC_ACTIVATE);
1193 return result;
1194 }
1195
mnemonicMatch(long mnemonicHandle, char key)1196 boolean mnemonicMatch (long mnemonicHandle, char key) {
1197 long keyval1 = GDK.gdk_keyval_to_lower (GDK.gdk_unicode_to_keyval (key));
1198 long keyval2 = GDK.gdk_keyval_to_lower (GTK.gtk_label_get_mnemonic_keyval (mnemonicHandle));
1199 return keyval1 == keyval2;
1200 }
1201
1202 /**
1203 * Notifies all of the receiver's listeners for events
1204 * of the given type that one such event has occurred by
1205 * invoking their <code>handleEvent()</code> method. The
1206 * event type is one of the event constants defined in class
1207 * <code>SWT</code>.
1208 *
1209 * @param eventType the type of event which has occurred
1210 * @param event the event data
1211 *
1212 * @exception SWTException <ul>
1213 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1214 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1215 * </ul>
1216 *
1217 * @see SWT
1218 * @see #addListener
1219 * @see #getListeners(int)
1220 * @see #removeListener(int, Listener)
1221 */
notifyListeners(int eventType, Event event)1222 public void notifyListeners (int eventType, Event event) {
1223 checkWidget();
1224 if (event == null) event = new Event ();
1225 sendEvent (eventType, event);
1226 }
1227
postEvent(int eventType)1228 void postEvent (int eventType) {
1229 sendEvent (eventType, null, false);
1230 }
1231
postEvent(int eventType, Event event)1232 void postEvent (int eventType, Event event) {
1233 sendEvent (eventType, event, false);
1234 }
1235
register()1236 void register () {
1237 if (handle == 0) return;
1238 if ((state & HANDLE) != 0) display.addWidget (handle, this);
1239 }
1240
release(boolean destroy)1241 void release (boolean destroy) {
1242 if ((state & DISPOSE_SENT) == 0) {
1243 state |= DISPOSE_SENT;
1244 sendEvent (SWT.Dispose);
1245 }
1246 if ((state & DISPOSED) == 0) {
1247 releaseChildren (destroy);
1248 }
1249 if ((state & RELEASED) == 0) {
1250 state |= RELEASED;
1251 if (destroy) {
1252 releaseParent ();
1253 releaseWidget ();
1254 destroyWidget ();
1255 } else {
1256 releaseWidget ();
1257 releaseHandle ();
1258 }
1259 }
1260 }
1261
releaseChildren(boolean destroy)1262 void releaseChildren (boolean destroy) {
1263 }
1264
releaseHandle()1265 void releaseHandle () {
1266 handle = 0;
1267 state |= DISPOSED;
1268 display = null;
1269 }
1270
releaseParent()1271 void releaseParent () {
1272 /* Do nothing */
1273 }
1274
releaseWidget()1275 void releaseWidget () {
1276 deregister ();
1277 eventTable = null;
1278 data = null;
1279 }
1280
1281 /**
1282 * Removes the listener from the collection of listeners who will
1283 * be notified when an event of the given type occurs. The event
1284 * type is one of the event constants defined in class <code>SWT</code>.
1285 *
1286 * @param eventType the type of event to listen for
1287 * @param listener the listener which should no longer be notified
1288 *
1289 * @exception IllegalArgumentException <ul>
1290 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1291 * </ul>
1292 * @exception SWTException <ul>
1293 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1294 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1295 * </ul>
1296 *
1297 * @see Listener
1298 * @see SWT
1299 * @see #addListener
1300 * @see #getListeners(int)
1301 * @see #notifyListeners
1302 */
removeListener(int eventType, Listener listener)1303 public void removeListener (int eventType, Listener listener) {
1304 checkWidget ();
1305 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1306 if (eventTable == null) return;
1307 eventTable.unhook (eventType, listener);
1308 }
1309
1310 /**
1311 * Removes the listener from the collection of listeners who will
1312 * be notified when an event of the given type occurs.
1313 * <p>
1314 * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
1315 * public API. It is marked public only so that it can be shared
1316 * within the packages provided by SWT. It should never be
1317 * referenced from application code.
1318 * </p>
1319 *
1320 * @param eventType the type of event to listen for
1321 * @param listener the listener which should no longer be notified
1322 *
1323 * @exception IllegalArgumentException <ul>
1324 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1325 * </ul>
1326 * @exception SWTException <ul>
1327 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1328 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1329 * </ul>
1330 *
1331 * @see Listener
1332 * @see #addListener
1333 *
1334 * @noreference This method is not intended to be referenced by clients.
1335 * @nooverride This method is not intended to be re-implemented or extended by clients.
1336 */
removeListener(int eventType, SWTEventListener handler)1337 protected void removeListener (int eventType, SWTEventListener handler) {
1338 checkWidget ();
1339 if (handler == null) error (SWT.ERROR_NULL_ARGUMENT);
1340 if (eventTable == null) return;
1341 eventTable.unhook (eventType, handler);
1342 }
1343
rendererGetPreferredWidthProc(long cell, long handle, long minimun_size, long natural_size)1344 long rendererGetPreferredWidthProc (long cell, long handle, long minimun_size, long natural_size) {
1345 return 0;
1346 }
1347
rendererRenderProc(long cell, long cr, long handle, long background_area, long cell_area, long flags)1348 long rendererRenderProc (long cell, long cr, long handle, long background_area, long cell_area, long flags) {
1349 return 0;
1350 }
1351
rendererSnapshotProc(long cell, long snapshot, long handle, long background_area, long cell_area, long flags)1352 long rendererSnapshotProc (long cell, long snapshot, long handle, long background_area, long cell_area, long flags) {
1353 return 0;
1354 }
1355
1356 /**
1357 * Marks the widget to be skinned.
1358 * <p>
1359 * The skin event is sent to the receiver's display when appropriate (usually before the next event
1360 * is handled). Widgets are automatically marked for skinning upon creation as well as when its skin
1361 * id or class changes. The skin id and/or class can be changed by calling {@link Display#setData(String, Object)}
1362 * with the keys {@link SWT#SKIN_ID} and/or {@link SWT#SKIN_CLASS}. Once the skin event is sent to a widget, it
1363 * will not be sent again unless <code>reskin(int)</code> is called on the widget or on an ancestor
1364 * while specifying the <code>SWT.ALL</code> flag.
1365 * </p>
1366 * <p>
1367 * The parameter <code>flags</code> may be either:
1368 * </p>
1369 * <dl>
1370 * <dt><b>{@link SWT#ALL}</b></dt>
1371 * <dd>all children in the receiver's widget tree should be skinned</dd>
1372 * <dt><b>{@link SWT#NONE}</b></dt>
1373 * <dd>only the receiver should be skinned</dd>
1374 * </dl>
1375 * @param flags the flags specifying how to reskin
1376 *
1377 * @exception SWTException
1378 * <ul>
1379 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1380 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1381 * </ul>
1382 * @since 3.6
1383 */
reskin(int flags)1384 public void reskin (int flags) {
1385 checkWidget ();
1386 reskinWidget ();
1387 if ((flags & SWT.ALL) != 0) reskinChildren (flags);
1388 }
1389
reskinChildren(int flags)1390 void reskinChildren (int flags) {
1391 }
1392
reskinWidget()1393 void reskinWidget() {
1394 if ((state & SKIN_NEEDED) != SKIN_NEEDED) {
1395 this.state |= SKIN_NEEDED;
1396 display.addSkinnableWidget(this);
1397 }
1398 }
1399
1400 /**
1401 * Removes the listener from the collection of listeners who will
1402 * be notified when the widget is disposed.
1403 *
1404 * @param listener the listener which should no longer be notified
1405 *
1406 * @exception IllegalArgumentException <ul>
1407 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1408 * </ul>
1409 * @exception SWTException <ul>
1410 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1411 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1412 * </ul>
1413 *
1414 * @see DisposeListener
1415 * @see #addDisposeListener
1416 */
removeDisposeListener(DisposeListener listener)1417 public void removeDisposeListener (DisposeListener listener) {
1418 checkWidget ();
1419 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1420 if (eventTable == null) return;
1421 eventTable.unhook (SWT.Dispose, listener);
1422 }
1423
sendEvent(Event event)1424 void sendEvent (Event event) {
1425 Display display = event.display;
1426 if (!display.filterEvent (event)) {
1427 if (eventTable != null) display.sendEvent(eventTable, event);
1428 }
1429 }
1430
sendEvent(int eventType)1431 void sendEvent (int eventType) {
1432 sendEvent (eventType, null, true);
1433 }
1434
sendEvent(int eventType, Event event)1435 void sendEvent (int eventType, Event event) {
1436 sendEvent (eventType, event, true);
1437 }
1438
sendEvent(int eventType, Event event, boolean send)1439 void sendEvent (int eventType, Event event, boolean send) {
1440 if (eventTable == null && !display.filters (eventType)) {
1441 return;
1442 }
1443 if (event == null) {
1444 event = new Event();
1445 }
1446 event.type = eventType;
1447 event.display = display;
1448 event.widget = this;
1449 if (event.time == 0) {
1450 event.time = display.getLastEventTime ();
1451 }
1452 if (send) {
1453 sendEvent (event);
1454 } else {
1455 display.postEvent (event);
1456 }
1457 }
1458
sendKeyEvent(int type, long event)1459 boolean sendKeyEvent (int type, long event) {
1460 int length = 0;
1461 long string = 0;
1462 if (GTK.GTK4) {
1463 /* TODO: GTK4 no access to key event string */
1464 } else {
1465 GdkEventKey gdkEvent = new GdkEventKey ();
1466 OS.memmove(gdkEvent, event, GdkEventKey.sizeof);
1467 length = gdkEvent.length;
1468 string = gdkEvent.string;
1469 }
1470
1471 if (string == 0 || OS.g_utf16_strlen (string, length) <= 1) {
1472 Event javaEvent = new Event ();
1473 javaEvent.time = GDK.gdk_event_get_time(event);
1474 if (!setKeyState (javaEvent, event)) return true;
1475 sendEvent (type, javaEvent);
1476 // widget could be disposed at this point
1477
1478 /*
1479 * It is possible (but unlikely), that application
1480 * code could have disposed the widget in the key
1481 * events. If this happens, end the processing of
1482 * the key by returning false.
1483 */
1484 if (isDisposed ()) return false;
1485 return javaEvent.doit;
1486 }
1487 byte [] buffer = new byte [length];
1488 C.memmove (buffer, string, length);
1489 char [] chars = Converter.mbcsToWcs (buffer);
1490 return sendIMKeyEvent (type, event, chars) != null;
1491 }
1492
sendIMKeyEvent(int type, long event, char [] chars)1493 char [] sendIMKeyEvent (int type, long event, char [] chars) {
1494 int index = 0, count = 0, state = 0;
1495 long ptr = 0;
1496 if (event == 0) {
1497 ptr = GTK3.gtk_get_current_event ();
1498 if (ptr != 0) {
1499 int eventType = GDK.gdk_event_get_event_type(ptr);
1500 eventType = Control.fixGdkEventTypeValues(eventType);
1501 switch (eventType) {
1502 case GDK.GDK_KEY_PRESS:
1503 case GDK.GDK_KEY_RELEASE:
1504 int [] eventState = new int[1];
1505 if (GTK.GTK4) {
1506 eventState[0] = GDK.gdk_event_get_modifier_state(event);
1507 } else {
1508 GDK.gdk_event_get_state(event, eventState);
1509 }
1510 state = eventState[0];
1511 break;
1512 default:
1513 event = 0;
1514 break;
1515 }
1516 } else {
1517 int [] buffer = new int [1];
1518 GTK3.gtk_get_current_event_state (buffer);
1519 state = buffer [0];
1520 }
1521 } else {
1522 ptr = event;
1523 }
1524 while (index < chars.length) {
1525 Event javaEvent = new Event ();
1526 if (ptr != 0 && chars.length <= 1) {
1527 setKeyState (javaEvent, ptr);
1528 } else {
1529 setInputState (javaEvent, state);
1530 }
1531 javaEvent.character = chars [index];
1532 sendEvent (type, javaEvent);
1533
1534 /*
1535 * It is possible (but unlikely), that application
1536 * code could have disposed the widget in the key
1537 * events. If this happens, end the processing of
1538 * the key by returning null.
1539 */
1540 if (isDisposed ()) {
1541 if (ptr != 0 && ptr != event) gdk_event_free (ptr);
1542 return null;
1543 }
1544 if (javaEvent.doit) chars [count++] = chars [index];
1545 index++;
1546 }
1547 if (ptr != 0 && ptr != event) gdk_event_free (ptr);
1548 if (count == 0) return null;
1549 if (index != count) {
1550 char [] result = new char [count];
1551 System.arraycopy (chars, 0, result, 0, count);
1552 return result;
1553 }
1554 return chars;
1555 }
1556
sendSelectionEvent(int eventType)1557 void sendSelectionEvent (int eventType) {
1558 sendSelectionEvent (eventType, null, false);
1559 }
1560
sendSelectionEvent(int eventType, Event event, boolean send)1561 void sendSelectionEvent (int eventType, Event event, boolean send) {
1562 if (eventTable == null && !display.filters (eventType)) {
1563 return;
1564 }
1565 if (event == null) event = new Event ();
1566 long ptr = GTK.GTK4 ? 0 : GTK3.gtk_get_current_event ();
1567 if (ptr != 0) {
1568 int currentEventType = GDK.gdk_event_get_event_type(ptr);
1569 currentEventType = Control.fixGdkEventTypeValues(currentEventType);
1570 switch (currentEventType) {
1571 case GDK.GDK_BUTTON_PRESS:
1572 case GDK.GDK_2BUTTON_PRESS:
1573 case GDK.GDK_BUTTON_RELEASE: {
1574 int [] eventButton = new int [1];
1575 if (GTK.GTK4) {
1576 eventButton[0] = GDK.gdk_button_event_get_button(ptr);
1577 } else {
1578 GDK.gdk_event_get_button(ptr, eventButton);
1579 }
1580
1581 setButtonState(event, eventButton [0]);
1582 }
1583 //$FALL-THROUGH$
1584 case GDK.GDK_KEY_PRESS:
1585 case GDK.GDK_KEY_RELEASE: {
1586 int [] state = new int[1];
1587 if (GTK.GTK4) {
1588 state[0] = GDK.gdk_event_get_modifier_state(ptr);
1589 } else {
1590 GDK.gdk_event_get_state(ptr, state);
1591 }
1592 setInputState (event, state [0]);
1593 break;
1594 }
1595 }
1596 gdk_event_free (ptr);
1597 }
1598 sendEvent (eventType, event, send);
1599 }
1600
1601 /**
1602 * Sets the application defined widget data associated
1603 * with the receiver to be the argument. The <em>widget
1604 * data</em> is a single, unnamed field that is stored
1605 * with every widget.
1606 * <p>
1607 * Applications may put arbitrary objects in this field. If
1608 * the object stored in the widget data needs to be notified
1609 * when the widget is disposed of, it is the application's
1610 * responsibility to hook the Dispose event on the widget and
1611 * do so.
1612 * </p>
1613 *
1614 * @param data the widget data
1615 *
1616 * @exception SWTException <ul>
1617 * <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li>
1618 * <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li>
1619 * </ul>
1620 *
1621 * @see #getData()
1622 */
setData(Object data)1623 public void setData (Object data) {
1624 checkWidget();
1625 if ((state & KEYED_DATA) != 0) {
1626 ((Object []) this.data) [0] = data;
1627 } else {
1628 this.data = data;
1629 }
1630 }
1631
1632 /**
1633 * Sets the application defined property of the receiver
1634 * with the specified name to the given value.
1635 * <p>
1636 * Applications may associate arbitrary objects with the
1637 * receiver in this fashion. If the objects stored in the
1638 * properties need to be notified when the widget is disposed
1639 * of, it is the application's responsibility to hook the
1640 * Dispose event on the widget and do so.
1641 * </p>
1642 *
1643 * @param key the name of the property
1644 * @param value the new value for the property
1645 *
1646 * @exception IllegalArgumentException <ul>
1647 * <li>ERROR_NULL_ARGUMENT - if the key is null</li>
1648 * </ul>
1649 * @exception SWTException <ul>
1650 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1651 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1652 * </ul>
1653 *
1654 * @see #getData(String)
1655 */
setData(String key, Object value)1656 public void setData (String key, Object value) {
1657 checkWidget();
1658 if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
1659
1660 if (key.equals (KEY_CHECK_SUBWINDOW)) {
1661 if (value != null && value instanceof Boolean) {
1662 if (((Boolean)value).booleanValue ()) {
1663 state |= CHECK_SUBWINDOW;
1664 } else {
1665 state &= ~CHECK_SUBWINDOW;
1666 }
1667 }
1668 return;
1669 }
1670
1671 int index = 1;
1672 Object [] table = null;
1673 if ((state & KEYED_DATA) != 0) {
1674 table = (Object []) data;
1675 while (index < table.length) {
1676 if (key.equals (table [index])) break;
1677 index += 2;
1678 }
1679 }
1680 if (value != null) {
1681 if ((state & KEYED_DATA) != 0) {
1682 if (index == table.length) {
1683 Object [] newTable = new Object [table.length + 2];
1684 System.arraycopy (table, 0, newTable, 0, table.length);
1685 data = table = newTable;
1686 }
1687 } else {
1688 table = new Object [3];
1689 table [0] = data;
1690 data = table;
1691 state |= KEYED_DATA;
1692 }
1693 table [index] = key;
1694 table [index + 1] = value;
1695 } else {
1696 if ((state & KEYED_DATA) != 0) {
1697 if (index != table.length) {
1698 int length = table.length - 2;
1699 if (length == 1) {
1700 data = table [0];
1701 state &= ~KEYED_DATA;
1702 } else {
1703 Object [] newTable = new Object [length];
1704 System.arraycopy (table, 0, newTable, 0, index);
1705 System.arraycopy (table, index + 2, newTable, index, length - index);
1706 data = newTable;
1707 }
1708 }
1709 }
1710 }
1711 if (key.equals(SWT.SKIN_CLASS) || key.equals(SWT.SKIN_ID)) this.reskin(SWT.ALL);
1712 if (key.equals(KEY_GTK_CSS) && value instanceof String) {
1713 long context = GTK.gtk_widget_get_style_context (cssHandle());
1714 long provider = GTK.gtk_css_provider_new();
1715 if (context != 0 && provider != 0) {
1716 GTK.gtk_style_context_add_provider (context, provider, GTK.GTK_STYLE_PROVIDER_PRIORITY_USER);
1717 if (GTK.GTK4) {
1718 GTK4.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs ((String) value, true), -1);
1719 } else {
1720 GTK3.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs ((String) value, true), -1, null);
1721 }
1722 OS.g_object_unref (provider);
1723 }
1724 }
1725 }
1726
1727 /**
1728 * @param fontDescription Font description in the form of
1729 * <code>PangoFontDescription*</code>. This pointer
1730 * will never be used by GTK after calling this
1731 * function, so it's safe to free it as soon as the
1732 * function completes.
1733 */
setFontDescription(long widget, long fontDescription)1734 void setFontDescription(long widget, long fontDescription) {
1735 if (GTK.GTK4) {
1736 long styleContext = GTK.gtk_widget_get_style_context(widget);
1737 long provider = GTK.gtk_css_provider_new();
1738 GTK.gtk_style_context_add_provider(styleContext, provider, GTK.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1739 OS.g_object_unref(provider);
1740
1741 String css = convertPangoFontDescriptionToCss(fontDescription);
1742 GTK4.gtk_css_provider_load_from_data(provider, Converter.javaStringToCString(css), -1);
1743 } else {
1744 // gtk_widget_override_font() copies the fields from 'fontDescription'
1745 // and does not remember the pointer passed to it.
1746 GTK3.gtk_widget_override_font(widget, fontDescription);
1747 long context = GTK.gtk_widget_get_style_context(widget);
1748 GTK3.gtk_style_context_invalidate(context);
1749 }
1750 }
1751
convertPangoFontDescriptionToCss(long fontDescription)1752 String convertPangoFontDescriptionToCss(long fontDescription) {
1753 String css = "* { ";
1754 int fontMask = OS.pango_font_description_get_set_fields(fontDescription);
1755
1756 if ((fontMask & OS.PANGO_FONT_MASK_FAMILY) != 0) {
1757 long fontFamily = OS.pango_font_description_get_family(fontDescription);
1758 css += "font-family: \"" + Converter.cCharPtrToJavaString(fontFamily, false) + "\";";
1759 }
1760
1761 if ((fontMask & OS.PANGO_FONT_MASK_WEIGHT) != 0) {
1762 int fontWeight = OS.pango_font_description_get_weight(fontDescription);
1763
1764 String weightString = fontWeight < OS.PANGO_WEIGHT_BOLD ? "normal" : "bold";
1765 css += "font-weight: " + weightString + ";";
1766 }
1767
1768 if ((fontMask & OS.PANGO_FONT_MASK_STYLE) != 0) {
1769 int fontStyle = OS.pango_font_description_get_style(fontDescription);
1770
1771 String styleString;
1772 switch (fontStyle) {
1773 case OS.PANGO_STYLE_NORMAL:
1774 styleString = "normal";
1775 break;
1776 case OS.PANGO_STYLE_ITALIC:
1777 styleString = "italic";
1778 break;
1779 default:
1780 styleString = "";
1781 break;
1782 }
1783
1784 css += "font-style: " + styleString + ";";
1785 }
1786
1787 if ((fontMask & OS.PANGO_FONT_MASK_SIZE) != 0) {
1788 int fontSize = OS.pango_font_description_get_size(fontDescription);
1789 css += "font-size: " + fontSize / OS.PANGO_SCALE + "pt;";
1790 }
1791
1792 css += " } ";
1793
1794 return css;
1795 }
1796
1797 void setButtonState (Event event, int eventButton) {
1798 switch (eventButton) {
1799 case 1: event.stateMask |= SWT.BUTTON1; break;
1800 case 2: event.stateMask |= SWT.BUTTON2; break;
1801 case 3: event.stateMask |= SWT.BUTTON3; break;
1802 case 4: event.stateMask |= SWT.BUTTON4; break;
1803 case 5: event.stateMask |= SWT.BUTTON5; break;
1804 default:
1805 }
1806 }
1807
1808 boolean setInputState (Event event, int state) {
1809 if ((state & GDK.GDK_MOD1_MASK) != 0) event.stateMask |= SWT.ALT;
1810 if ((state & GDK.GDK_SHIFT_MASK) != 0) event.stateMask |= SWT.SHIFT;
1811 if ((state & GDK.GDK_CONTROL_MASK) != 0) event.stateMask |= SWT.CONTROL;
1812 if ((state & GDK.GDK_BUTTON1_MASK) != 0) event.stateMask |= SWT.BUTTON1;
1813 if ((state & GDK.GDK_BUTTON2_MASK) != 0) event.stateMask |= SWT.BUTTON2;
1814 if ((state & GDK.GDK_BUTTON3_MASK) != 0) event.stateMask |= SWT.BUTTON3;
1815 return true;
1816 }
1817
1818 boolean setKeyState (Event javaEvent, long event) {
1819 long string = 0;
1820 int length = 0;
1821 int group;
1822
1823 int [] eventKeyval = new int [1];
1824 int [] eventState = new int [1];
1825 if (GTK.GTK4) {
1826 eventKeyval[0] = GDK.gdk_key_event_get_keyval(event);
1827 eventState[0] = GDK.gdk_event_get_modifier_state(event);
1828 } else {
1829 GDK.gdk_event_get_keyval(event, eventKeyval);
1830 GDK.gdk_event_get_state(event, eventState);
1831 }
1832
1833 if (GTK.GTK4) {
1834 group = GDK.gdk_key_event_get_layout(event);
1835 } else {
1836 GdkEventKey gdkEvent = new GdkEventKey ();
1837 OS.memmove(gdkEvent, event, GdkEventKey.sizeof);
1838 length = gdkEvent.length;
1839 string = gdkEvent.string;
1840 group = gdkEvent.group;
1841 }
1842
1843 if (string != 0 && OS.g_utf16_strlen (string, length) > 1) return false;
1844 boolean isNull = false;
1845 javaEvent.keyCode = Display.translateKey (eventKeyval[0]);
1846 switch (eventKeyval[0]) {
1847 case GDK.GDK_BackSpace: javaEvent.character = SWT.BS; break;
1848 case GDK.GDK_Linefeed: javaEvent.character = SWT.LF; break;
1849 case GDK.GDK_KP_Enter:
1850 case GDK.GDK_Return: javaEvent.character = SWT.CR; break;
1851 case GDK.GDK_KP_Delete:
1852 case GDK.GDK_Delete: javaEvent.character = SWT.DEL; break;
1853 case GDK.GDK_Escape: javaEvent.character = SWT.ESC; break;
1854 case GDK.GDK_Tab:
1855 case GDK.GDK_ISO_Left_Tab: javaEvent.character = SWT.TAB; break;
1856 default: {
1857 if (javaEvent.keyCode == 0) {
1858 int [] keyval = new int [1];
1859 int [] effective_group = new int [1], level = new int [1], consumed_modifiers = new int [1];
1860 /* If current group is not a Latin layout, get the most Latin Layout group from input source. */
1861 Map<Integer, Integer> groupLatinKeysCount = display.getGroupKeysCount();
1862 if (!groupLatinKeysCount.containsKey(group)) {
1863 group = display.getLatinKeyGroup();
1864 }
1865
1866 long keymap = 0;
1867 long display = GDK.gdk_display_get_default();
1868 if (GTK.GTK4) {
1869 //TODO: GTK4 Get keymap or find alternative for gdk_keymap_translate_keyboard_state (no longer exist in GTK4)
1870 } else {
1871 keymap = GDK.gdk_keymap_get_for_display(display);
1872 }
1873
1874 short [] keyCode = new short [1];
1875 if (GTK.GTK4) {
1876 keyCode[0] = (short) GDK.gdk_key_event_get_keycode(event);
1877 javaEvent.keyCode = keyCode[0];
1878 } else {
1879 GDK.gdk_event_get_keycode(event, keyCode);
1880 if (GDK.gdk_keymap_translate_keyboard_state (keymap, keyCode[0],
1881 0, group, keyval, effective_group, level, consumed_modifiers)) {
1882 javaEvent.keyCode = (int) GDK.gdk_keyval_to_unicode (keyval [0]);
1883 }
1884 }
1885 }
1886 int key = eventKeyval[0];
1887 if ((eventState[0] & GDK.GDK_CONTROL_MASK) != 0 && (0 <= key && key <= 0x7F)) {
1888 if ('a' <= key && key <= 'z') key -= 'a' - 'A';
1889 if (64 <= key && key <= 95) key -= 64;
1890 javaEvent.character = (char) key;
1891 isNull = eventKeyval[0] == '@' && key == 0;
1892 } else {
1893 javaEvent.character = (char) GDK.gdk_keyval_to_unicode (key);
1894 }
1895 }
1896 }
1897 setLocationState (javaEvent, event);
1898 if (javaEvent.keyCode == 0 && javaEvent.character == 0) {
1899 if (!isNull) return false;
1900 }
1901 return setInputState (javaEvent, eventState[0]);
1902 }
1903
setLocationState(Event event, long eventPtr)1904 void setLocationState (Event event, long eventPtr) {
1905 int [] eventKeyval = new int[1];
1906 if (GTK.GTK4) {
1907 eventKeyval[0] = GDK.gdk_key_event_get_keyval(eventPtr);
1908 } else {
1909 GDK.gdk_event_get_keyval(eventPtr, eventKeyval);
1910 }
1911
1912 switch (eventKeyval[0]) {
1913 case GDK.GDK_Alt_L:
1914 case GDK.GDK_Shift_L:
1915 case GDK.GDK_Control_L:
1916 event.keyLocation = SWT.LEFT;
1917 break;
1918 case GDK.GDK_Alt_R:
1919 case GDK.GDK_Shift_R:
1920 case GDK.GDK_Control_R:
1921 event.keyLocation = SWT.RIGHT;
1922 break;
1923 case GDK.GDK_KP_0:
1924 case GDK.GDK_KP_1:
1925 case GDK.GDK_KP_2:
1926 case GDK.GDK_KP_3:
1927 case GDK.GDK_KP_4:
1928 case GDK.GDK_KP_5:
1929 case GDK.GDK_KP_6:
1930 case GDK.GDK_KP_7:
1931 case GDK.GDK_KP_8:
1932 case GDK.GDK_KP_9:
1933 case GDK.GDK_KP_Add:
1934 case GDK.GDK_KP_Decimal:
1935 case GDK.GDK_KP_Delete:
1936 case GDK.GDK_KP_Divide:
1937 case GDK.GDK_KP_Down:
1938 case GDK.GDK_KP_End:
1939 case GDK.GDK_KP_Enter:
1940 case GDK.GDK_KP_Equal:
1941 case GDK.GDK_KP_Home:
1942 case GDK.GDK_KP_Insert:
1943 case GDK.GDK_KP_Left:
1944 case GDK.GDK_KP_Multiply:
1945 case GDK.GDK_KP_Page_Down:
1946 case GDK.GDK_KP_Page_Up:
1947 case GDK.GDK_KP_Right:
1948 case GDK.GDK_KP_Subtract:
1949 case GDK.GDK_KP_Up:
1950 case GDK.GDK_Num_Lock:
1951 event.keyLocation = SWT.KEYPAD;
1952 break;
1953 }
1954 }
1955
setOrientation(boolean create)1956 void setOrientation (boolean create) {
1957 }
1958
setTabGroupFocus(boolean next)1959 boolean setTabGroupFocus (boolean next) {
1960 return setTabItemFocus (next);
1961 }
1962
setTabItemFocus(boolean next)1963 boolean setTabItemFocus (boolean next) {
1964 return false;
1965 }
1966
shellMapProc(long handle, long arg0, long user_data)1967 long shellMapProc (long handle, long arg0, long user_data) {
1968 return 0;
1969 }
1970
sizeAllocateProc(long handle, long arg0, long user_data)1971 long sizeAllocateProc (long handle, long arg0, long user_data) {
1972 return 0;
1973 }
1974
sizeRequestProc(long handle, long arg0, long user_data)1975 long sizeRequestProc (long handle, long arg0, long user_data) {
1976 return 0;
1977 }
1978
1979 /**
1980 * Converts an incoming snapshot into a gtk_draw() call, complete with
1981 * a Cairo context.
1982 *
1983 * @param handle the widget receiving the snapshot
1984 * @param snapshot the actual GtkSnapshot
1985 */
snapshotToDraw(long handle, long snapshot)1986 void snapshotToDraw (long handle, long snapshot) {
1987 GtkAllocation allocation = new GtkAllocation ();
1988 GTK.gtk_widget_get_allocation(handle, allocation);
1989 long rect = Graphene.graphene_rect_alloc();
1990 Graphene.graphene_rect_init(rect, 0, 0, allocation.width, allocation.height);
1991 long cairo = GTK4.gtk_snapshot_append_cairo(snapshot, rect);
1992 if (cairo != 0) gtk_draw(handle, cairo);
1993 Graphene.graphene_rect_free(rect);
1994 return;
1995 }
1996
gtk_widget_get_window(long widget)1997 long gtk_widget_get_window (long widget){
1998 GTK.gtk_widget_realize(widget);
1999 return GTK3.gtk_widget_get_window (widget);
2000 }
2001
gtk_widget_get_surface(long widget)2002 long gtk_widget_get_surface (long widget){
2003 GTK.gtk_widget_realize(widget);
2004 return GTK4.gtk_native_get_surface(GTK4.gtk_widget_get_native (widget));
2005 }
2006
gdk_window_get_size(long drawable, int[] width, int[] height)2007 void gdk_window_get_size (long drawable, int[] width, int[] height) {
2008 width[0] = GDK.gdk_window_get_width (drawable);
2009 height[0] = GDK.gdk_window_get_height (drawable);
2010 }
2011
gdk_surface_get_size(long surface, int[] width, int[] height)2012 void gdk_surface_get_size (long surface, int[] width, int[] height) {
2013 width[0] = GDK.gdk_surface_get_width (surface);
2014 height[0] = GDK.gdk_surface_get_height (surface);
2015 }
2016
2017 /**
2018 * GTK4 does not hand out copies of events anymore, only references.
2019 * Call gdk_event_free() on GTK3 and g_object_unref() on GTK4.
2020 *
2021 * @param event the event to be freed
2022 */
gdk_event_free(long event)2023 void gdk_event_free (long event) {
2024 if (event == 0) return;
2025 if (GTK.GTK4) {
2026 GDK.gdk_event_unref(event);
2027 } else {
2028 GDK.gdk_event_free(event);
2029 }
2030 }
2031
2032 /**
2033 * Wrapper function for gdk_event_get_surface() on GTK4,
2034 * and gdk_event_get_window() on GTK3.
2035 *
2036 * @param event the event whose window or surface to fetch
2037 * @return the GdkWindow or GdkSurface associated with the event
2038 */
gdk_event_get_surface_or_window(long event)2039 long gdk_event_get_surface_or_window(long event) {
2040 if (event == 0) return 0;
2041 if (GTK.GTK4) {
2042 return GDK.gdk_event_get_surface(event);
2043 } else {
2044 return GDK.gdk_event_get_window(event);
2045 }
2046 }
2047
2048 /**
2049 * Wrapper function for gdk_event_get_state()
2050 * @param event pointer to the GdkEvent.
2051 * @return the keymask to be used with constants like
2052 * OS.GDK_SHIFT_MASK / OS.GDK_CONTROL_MASK / OS.GDK_MOD1_MASK etc..
2053 */
gdk_event_get_state(long event)2054 int gdk_event_get_state (long event) {
2055 int [] state = new int[1];
2056 if (GTK.GTK4) {
2057 state[0] = GDK.gdk_event_get_modifier_state(event);
2058 } else {
2059 GDK.gdk_event_get_state(event, state);
2060 }
2061
2062 return state[0];
2063 }
2064
2065
gtk_box_new(int orientation, boolean homogeneous, int spacing)2066 long gtk_box_new (int orientation, boolean homogeneous, int spacing) {
2067 long box = GTK.gtk_box_new (orientation, spacing);
2068 GTK.gtk_box_set_homogeneous (box, homogeneous);
2069 return box;
2070 }
2071
gtk_box_set_child_packing(long box, long child, boolean expand, boolean fill, int padding, int pack_type)2072 void gtk_box_set_child_packing (long box, long child, boolean expand, boolean fill, int padding, int pack_type) {
2073 if (GTK.GTK4) {
2074 GTK.gtk_widget_set_hexpand(child, expand);
2075 GTK.gtk_widget_set_vexpand(child, expand);
2076 if (fill) {
2077 GTK.gtk_widget_set_halign(child, GTK.GTK_ALIGN_FILL);
2078 GTK.gtk_widget_set_valign(child, GTK.GTK_ALIGN_FILL);
2079 }
2080 } else {
2081 GTK3.gtk_box_set_child_packing(box, child, expand, fill, padding, pack_type);
2082 }
2083 }
2084
gtk_box_pack_end(long box, long child, boolean expand, boolean fill, int padding)2085 void gtk_box_pack_end (long box, long child, boolean expand, boolean fill, int padding) {
2086 if (GTK.GTK4) {
2087 GTK.gtk_widget_set_hexpand(child, expand);
2088 GTK.gtk_widget_set_vexpand(child, expand);
2089 if (fill) {
2090 GTK.gtk_widget_set_halign(child, GTK.GTK_ALIGN_FILL);
2091 GTK.gtk_widget_set_valign(child, GTK.GTK_ALIGN_FILL);
2092 }
2093 GTK4.gtk_box_append(box, child);
2094 } else {
2095 GTK3.gtk_box_pack_end(box, child, expand, fill, padding);
2096 }
2097 }
2098
gdk_pointer_grab(long gdkResource, int grab_ownership, boolean owner_events, int event_mask, long confine_to, long cursor, int time_)2099 int gdk_pointer_grab (long gdkResource, int grab_ownership, boolean owner_events, int event_mask, long confine_to, long cursor, int time_) {
2100 long display = 0;
2101 if (GTK.GTK4) {
2102 if( gdkResource != 0) {
2103 display = GDK.gdk_surface_get_display (gdkResource);
2104 }
2105 } else {
2106 if( gdkResource != 0) {
2107 display = GDK.gdk_window_get_display (gdkResource);
2108 } else {
2109 gdkResource = GDK.gdk_get_default_root_window ();
2110 display = GDK.gdk_window_get_display (gdkResource);
2111 }
2112 }
2113 long seat = GDK.gdk_display_get_default_seat(display);
2114 if (gdkSeatGrabPrepareFunc == null) {
2115 gdkSeatGrabPrepareFunc = new Callback(Widget.class, "GdkSeatGrabPrepareFunc", 3); //$NON-NLS-1$
2116 }
2117 return GDK.gdk_seat_grab(seat, gdkResource, GDK.GDK_SEAT_CAPABILITY_ALL_POINTING, owner_events, cursor, 0, gdkSeatGrabPrepareFunc.getAddress(), gdkResource);
2118 }
2119
gdk_pointer_ungrab(long gdkResource, int time_)2120 void gdk_pointer_ungrab (long gdkResource, int time_) {
2121 long display = GTK.GTK4? GDK.gdk_surface_get_display(gdkResource) : GDK.gdk_window_get_display (gdkResource);
2122 long seat = GDK.gdk_display_get_default_seat(display);
2123 GDK.gdk_seat_ungrab(seat);
2124 }
2125
GdkSeatGrabPrepareFunc(long gdkSeat, long gdkResource, long userData_gdkResource)2126 static long GdkSeatGrabPrepareFunc (long gdkSeat, long gdkResource, long userData_gdkResource) {
2127 if (userData_gdkResource != 0) {
2128 if (GTK.GTK4) {
2129 /* TODO: GTK does not provide a gdk_surface_show, probably will require use of the present api */
2130 } else {
2131 GDK.gdk_window_show(userData_gdkResource);
2132 }
2133 }
2134 return 0;
2135 }
2136
2137 /**
2138 * Returns a string containing a concise, human-readable
2139 * description of the receiver.
2140 *
2141 * @return a string representation of the receiver
2142 */
2143 @Override
toString()2144 public String toString () {
2145 String string = "*Disposed*";
2146 if (!isDisposed ()) {
2147 string = "*Wrong Thread*";
2148 if (isValidThread ()) string = getNameText ();
2149 }
2150 return getName () + " {" + string + "}";
2151 }
2152
topHandle()2153 long topHandle () {
2154 return handle;
2155 }
2156
timerProc(long widget)2157 long timerProc (long widget) {
2158 return 0;
2159 }
2160
translateTraversal(int event)2161 boolean translateTraversal (int event) {
2162 return false;
2163 }
2164
enterMotionScrollProc(long controller, long handle, double x, double y, long user_data)2165 long enterMotionScrollProc(long controller, long handle, double x, double y, long user_data) {
2166 long result = 0;
2167 long event = GTK4.gtk_event_controller_get_current_event(controller);
2168
2169 switch ((int)user_data) {
2170 case ENTER:
2171 result = gtk_enter_notify_event(handle, event);
2172 break;
2173 case MOTION:
2174 result = gtk_motion_notify_event(handle, event);
2175 break;
2176 case MOTION_INVERSE:
2177 result = 1;
2178 break;
2179 case SCROLL:
2180 result = gtk_scroll_event(handle, event);
2181 break;
2182 }
2183
2184 return result;
2185 }
2186
focusProc(long controller, long handle, long user_data)2187 long focusProc(long controller, long handle, long user_data) {
2188 long result = 0;
2189 long event = GTK4.gtk_event_controller_get_current_event(controller);
2190
2191 switch ((int)user_data) {
2192 case FOCUS_IN:
2193 result = gtk_focus_in_event(handle, event);
2194 break;
2195 case FOCUS_OUT:
2196 result = gtk_focus_out_event(handle, event);
2197 break;
2198 }
2199
2200 return result;
2201 }
2202
keyPressReleaseProc(long controller, long handle, int keyval, int keycode, int state, long user_data)2203 long keyPressReleaseProc(long controller, long handle, int keyval, int keycode, int state, long user_data) {
2204 long result = 0;
2205 long event = GTK4.gtk_event_controller_get_current_event(controller);
2206
2207 switch ((int)user_data) {
2208 case KEY_PRESSED:
2209 result = gtk_key_press_event(handle, event);
2210 break;
2211 case KEY_RELEASED:
2212 result = gtk_key_release_event(handle, event);
2213 break;
2214 }
2215
2216 return result;
2217 }
2218
gesturePressReleaseProc(long gesture, int n_press, double x, double y, long user_data)2219 void gesturePressReleaseProc(long gesture, int n_press, double x, double y, long user_data) {
2220 long event = GTK4.gtk_event_controller_get_current_event(gesture);
2221
2222 switch ((int)user_data) {
2223 case GESTURE_PRESSED:
2224 gtk_gesture_press_event(gesture, n_press, x, y, event);
2225 break;
2226 case GESTURE_RELEASED:
2227 gtk_gesture_release_event(gesture, n_press, x, y, event);
2228 break;
2229 }
2230 }
2231
leaveProc(long controller, long handle, long user_data)2232 long leaveProc(long controller, long handle, long user_data) {
2233 long result = 0;
2234 long event = GTK4.gtk_event_controller_get_current_event(controller);
2235
2236 switch ((int)user_data) {
2237 case LEAVE:
2238 result = gtk_leave_notify_event(handle, event);
2239 break;
2240 }
2241
2242 return result;
2243 }
2244
notifyProc(long object, long arg0, long user_data)2245 long notifyProc (long object, long arg0, long user_data) {
2246 switch ((int)user_data) {
2247 case DPI_CHANGED: return dpiChanged(object, arg0);
2248 case NOTIFY_STATE: return notifyState(object, arg0);
2249 }
2250 return 0;
2251 }
2252
notifyState(long object, long argo0)2253 long notifyState (long object, long argo0) {
2254 return 0;
2255 }
2256
windowProc(long handle, long user_data)2257 long windowProc (long handle, long user_data) {
2258 switch ((int)user_data) {
2259 case ACTIVATE: return gtk_activate (handle);
2260 case CHANGED: return gtk_changed (handle);
2261 case CLICKED: return gtk_clicked (handle);
2262 case CLOSE_REQUEST: return gtk_close_request (handle);
2263 case CREATE_MENU_PROXY: return gtk_create_menu_proxy (handle);
2264 case DAY_SELECTED: return gtk_day_selected (handle);
2265 case DAY_SELECTED_DOUBLE_CLICK: return gtk_day_selected_double_click (handle);
2266 case HIDE: return gtk_hide (handle);
2267 case GRAB_FOCUS: return gtk_grab_focus (handle);
2268 case MAP: return gtk_map (handle);
2269 case MONTH_CHANGED: return gtk_month_changed (handle);
2270 case OUTPUT: return gtk_output (handle);
2271 case POPUP_MENU: return gtk_popup_menu (handle);
2272 case PREEDIT_CHANGED: return gtk_preedit_changed (handle);
2273 case REALIZE: return gtk_realize (handle);
2274 case START_INTERACTIVE_SEARCH: return gtk_start_interactive_search (handle);
2275 case STYLE_UPDATED: return gtk_style_updated (handle);
2276 case SELECT: return gtk_select (handle);
2277 case SELECTION_DONE: return gtk_selection_done (handle);
2278 case SHOW: return gtk_show (handle);
2279 case VALUE_CHANGED: return gtk_value_changed(handle);
2280 case UNMAP: return gtk_unmap (handle);
2281 case UNREALIZE: return gtk_unrealize (handle);
2282 default: return 0;
2283 }
2284 }
2285
windowProc(long handle, long arg0, long user_data)2286 long windowProc (long handle, long arg0, long user_data) {
2287 switch ((int)user_data) {
2288 case EXPOSE_EVENT_INVERSE: {
2289 if (GTK.GTK_IS_CONTAINER (handle)) {
2290 return gtk_draw (handle, arg0);
2291 }
2292 return 0;
2293 }
2294 case BUTTON_PRESS_EVENT_INVERSE:
2295 case BUTTON_RELEASE_EVENT_INVERSE:
2296 case MOTION_NOTIFY_EVENT_INVERSE: {
2297 return 1;
2298 }
2299 case BUTTON_PRESS_EVENT: return gtk_button_press_event (handle, arg0);
2300 case BUTTON_RELEASE_EVENT: return gtk_button_release_event (handle, arg0);
2301 case COMMIT: return gtk_commit (handle, arg0);
2302 case CONFIGURE_EVENT: return gtk_configure_event (handle, arg0);
2303 case DELETE_EVENT: return gtk_delete_event (handle, arg0);
2304 case ENTER_NOTIFY_EVENT: return gtk_enter_notify_event (handle, arg0);
2305 case EVENT_AFTER: return gtk_event_after (handle, arg0);
2306 case EXPOSE_EVENT: {
2307 if (!GTK.GTK_IS_CONTAINER (handle)) {
2308 return gtk_draw (handle, arg0);
2309 }
2310 return 0;
2311 }
2312 case FOCUS: return gtk_focus (handle, arg0);
2313 case FOCUS_IN_EVENT: return gtk_focus_in_event (handle, arg0);
2314 case FOCUS_OUT_EVENT: return gtk_focus_out_event (handle, arg0);
2315 case KEY_PRESS_EVENT: return gtk_key_press_event (handle, arg0);
2316 case KEY_RELEASE_EVENT: return gtk_key_release_event (handle, arg0);
2317 case INPUT: return gtk_input (handle, arg0);
2318 case LEAVE_NOTIFY_EVENT: return gtk_leave_notify_event (handle, arg0);
2319 case MAP_EVENT: return gtk_map_event (handle, arg0);
2320 case MNEMONIC_ACTIVATE: return gtk_mnemonic_activate (handle, arg0);
2321 case MOTION_NOTIFY_EVENT: return gtk_motion_notify_event (handle, arg0);
2322 case MOVE_FOCUS: return gtk_move_focus (handle, arg0);
2323 case POPULATE_POPUP: return gtk_populate_popup (handle, arg0);
2324 case SCROLL_EVENT: return gtk_scroll_event (handle, arg0);
2325 case SHOW_HELP: return gtk_show_help (handle, arg0);
2326 case SIZE_ALLOCATE: return gtk_size_allocate (handle, arg0);
2327 case TOGGLED: return gtk_toggled (handle, arg0);
2328 case UNMAP_EVENT: return gtk_unmap_event (handle, arg0);
2329 case WINDOW_STATE_EVENT: return gtk_window_state_event (handle, arg0);
2330 case ROW_DELETED: return gtk_row_deleted (handle, arg0);
2331 default: return 0;
2332 }
2333 }
2334
windowProc(long handle, long arg0, long arg1, long user_data)2335 long windowProc (long handle, long arg0, long arg1, long user_data) {
2336 switch ((int)user_data) {
2337 case DELETE_RANGE: return gtk_delete_range (handle, arg0, arg1);
2338 case DELETE_TEXT: return gtk_delete_text (handle, arg0, arg1);
2339 case ICON_RELEASE: return gtk_icon_release (handle, arg0, arg1);
2340 case ROW_ACTIVATED: return gtk_row_activated (handle, arg0, arg1);
2341 case SCROLL_CHILD: return gtk_scroll_child (handle, arg0, arg1);
2342 case STATUS_ICON_POPUP_MENU: return gtk_status_icon_popup_menu (handle, arg0, arg1);
2343 case SWITCH_PAGE: return gtk_switch_page(handle, arg0, (int)arg1);
2344 case TEST_COLLAPSE_ROW: return gtk_test_collapse_row (handle, arg0, arg1);
2345 case TEST_EXPAND_ROW: return gtk_test_expand_row(handle, arg0, arg1);
2346 case ROW_INSERTED: return gtk_row_inserted (handle, arg0, arg1);
2347 case ROW_HAS_CHILD_TOGGLED: return gtk_row_has_child_toggled(handle, arg0, arg1);
2348 default: return 0;
2349 }
2350 }
2351
windowProc(long handle, long arg0, long arg1, long arg2, long user_data)2352 long windowProc (long handle, long arg0, long arg1, long arg2, long user_data) {
2353 switch ((int)user_data) {
2354 case EXPAND_COLLAPSE_CURSOR_ROW: return gtk_expand_collapse_cursor_row (handle, arg0, arg1, arg2);
2355 case INSERT_TEXT: return gtk_insert_text (handle, arg0, arg1, arg2);
2356 case TEXT_BUFFER_INSERT_TEXT: return gtk_text_buffer_insert_text (handle, arg0, arg1, arg2);
2357 default: return 0;
2358 }
2359 }
2360
windowProc(long handle, long arg0, long arg1, long arg2, long arg3, long user_data)2361 long windowProc (long handle, long arg0, long arg1, long arg2, long arg3, long user_data) {
2362 switch ((int)user_data) {
2363 case POPPED_UP: return gtk_menu_popped_up (handle, arg0, arg1, arg2, arg3);
2364 default: return 0;
2365 }
2366 }
2367
gtk_cell_renderer_get_preferred_size(long cell, long widget, int[] width, int[] height)2368 void gtk_cell_renderer_get_preferred_size (long cell, long widget, int[] width, int[] height) {
2369 GtkRequisition minimum_size = new GtkRequisition ();
2370 GTK.gtk_cell_renderer_get_preferred_size (cell, widget, minimum_size, null);
2371 if (width != null) width [0] = minimum_size.width;
2372 if (height != null) height[0] = minimum_size.height;
2373 }
2374
gtk_widget_get_preferred_size(long widget, GtkRequisition requisition)2375 void gtk_widget_get_preferred_size (long widget, GtkRequisition requisition){
2376 GTK.gtk_widget_get_preferred_size (widget, requisition, null);
2377 }
2378
2379 /**
2380 * Retrieves the amount of space around the outside of the container.
2381 * On GTK3: this is done using gtk_container_get_border_width.
2382 * On GTK4: this is done by returning the max margin on any side.
2383 * @param handle
2384 * @return amount of space around the outside of the container.
2385 */
gtk_container_get_border_width_or_margin(long handle)2386 int gtk_container_get_border_width_or_margin (long handle) {
2387 if (GTK.GTK4) {
2388 int marginTop = GTK.gtk_widget_get_margin_top(handle);
2389 int marginBottom = GTK.gtk_widget_get_margin_bottom(handle);
2390 int marginStart = GTK.gtk_widget_get_margin_start(handle);
2391 int marginEnd = GTK.gtk_widget_get_margin_end(handle);
2392 return Math.max(Math.max(marginTop, marginBottom), Math.max(marginStart, marginEnd));
2393 } else {
2394 return GTK3.gtk_container_get_border_width(handle);
2395 }
2396 }
2397 /**
2398 * Sets the border width of the container to all sides of the container.
2399 * @param handle
2400 * @param border_width
2401 */
gtk_container_set_border_width(long handle, int border_width)2402 void gtk_container_set_border_width (long handle, int border_width) {
2403 if (GTK.GTK4) {
2404 GTK.gtk_widget_set_margin_top(handle, border_width);
2405 GTK.gtk_widget_set_margin_bottom(handle, border_width);
2406 GTK.gtk_widget_set_margin_start(handle, border_width);
2407 GTK.gtk_widget_set_margin_end(handle, border_width);
2408 } else {
2409 GTK3.gtk_container_set_border_width (handle, border_width);
2410 }
2411 }
2412
2413 }
2414