1 /******************************************************************************* 2 * Copyright (c) 2000, 2008 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 * Port to the D programming language: 11 * Frank Benoit <benoit@tionex.de> 12 *******************************************************************************/ 13 module org.eclipse.swt.widgets.Control; 14 15 import java.lang.all; 16 17 18 import org.eclipse.swt.SWT; 19 //import org.eclipse.swt.accessibility.Accessible; 20 import org.eclipse.swt.events.ControlListener; 21 import org.eclipse.swt.events.FocusListener; 22 import org.eclipse.swt.events.HelpListener; 23 import org.eclipse.swt.events.KeyListener; 24 import org.eclipse.swt.events.MouseListener; 25 import org.eclipse.swt.events.MouseMoveListener; 26 import org.eclipse.swt.events.MouseTrackListener; 27 import org.eclipse.swt.events.PaintListener; 28 import org.eclipse.swt.events.TraverseListener; 29 import org.eclipse.swt.events.DragDetectListener; 30 import org.eclipse.swt.events.MenuDetectListener; 31 import org.eclipse.swt.events.MouseWheelListener; 32 import org.eclipse.swt.graphics.Color; 33 import org.eclipse.swt.graphics.Cursor; 34 import org.eclipse.swt.graphics.Device; 35 import org.eclipse.swt.graphics.Drawable; 36 import org.eclipse.swt.graphics.Font; 37 import org.eclipse.swt.graphics.GC; 38 import org.eclipse.swt.graphics.GCData; 39 import org.eclipse.swt.graphics.Image; 40 import org.eclipse.swt.graphics.Point; 41 import org.eclipse.swt.graphics.Rectangle; 42 import org.eclipse.swt.graphics.Region; 43 import org.eclipse.swt.internal.Converter; 44 import org.eclipse.swt.internal.SWTEventListener; 45 import org.eclipse.swt.internal.accessibility.gtk.ATK; 46 import org.eclipse.swt.internal.gtk.OS; 47 import org.eclipse.swt.widgets.Composite; 48 import org.eclipse.swt.widgets.Decorations; 49 import org.eclipse.swt.widgets.Display; 50 import org.eclipse.swt.widgets.Event; 51 import org.eclipse.swt.widgets.Listener; 52 import org.eclipse.swt.widgets.Menu; 53 import org.eclipse.swt.widgets.Monitor; 54 import org.eclipse.swt.widgets.Shell; 55 import org.eclipse.swt.widgets.TypedListener; 56 import org.eclipse.swt.widgets.Widget; 57 import org.eclipse.swt.accessibility.Accessible; 58 59 import java.lang.Thread; 60 61 62 /** 63 * Control is the abstract superclass of all windowed user interface classes. 64 * <p> 65 * <dl> 66 * <dt><b>Styles:</b> 67 * <dd>BORDER</dd> 68 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd> 69 * <dt><b>Events:</b> 70 * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter, 71 * MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize, Traverse</dd> 72 * </dl> 73 * </p><p> 74 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified. 75 * </p><p> 76 * IMPORTANT: This class is intended to be subclassed <em>only</em> 77 * within the SWT implementation. 78 * </p> 79 * 80 * @see <a href="http://www.eclipse.org/swt/snippets/#control">Control snippets</a> 81 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a> 82 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 83 */ 84 public abstract class Control : Widget, Drawable { 85 86 alias Widget.mnemonicHit mnemonicHit; 87 alias Widget.mnemonicMatch mnemonicMatch; 88 alias Widget.setForegroundColor setForegroundColor; 89 alias Widget.translateTraversal translateTraversal; 90 alias Widget.windowProc windowProc; 91 92 GtkWidget* fixedHandle; 93 GdkWindow* redrawWindow; 94 GdkWindow* enableWindow; 95 int drawCount; 96 Composite parent; 97 Cursor cursor; 98 Menu menu; 99 Image backgroundImage; 100 Font font; 101 Region region; 102 String toolTipText; 103 Object layoutData; 104 Accessible accessible; 105 106 this () { 107 } 108 109 /** 110 * Constructs a new instance of this class given its parent 111 * and a style value describing its behavior and appearance. 112 * <p> 113 * The style value is either one of the style constants defined in 114 * class <code>SWT</code> which is applicable to instances of this 115 * class, or must be built by <em>bitwise OR</em>'ing together 116 * (that is, using the <code>int</code> "|" operator) two or more 117 * of those <code>SWT</code> style constants. The class description 118 * lists the style constants that are applicable to the class. 119 * Style bits are also inherited from superclasses. 120 * </p> 121 * 122 * @param parent a composite control which will be the parent of the new instance (cannot be null) 123 * @param style the style of control to construct 124 * 125 * @exception IllegalArgumentException <ul> 126 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> 127 * </ul> 128 * @exception SWTException <ul> 129 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 130 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 131 * </ul> 132 * 133 * @see SWT#BORDER 134 * @see Widget#checkSubclass 135 * @see Widget#getStyle 136 */ 137 public this (Composite parent, int style) { 138 super (parent, style); 139 this.parent = parent; 140 createWidget (0); 141 } 142 143 Font defaultFont () { 144 return display.getSystemFont (); 145 } 146 147 override void deregister () { 148 super.deregister (); 149 if (fixedHandle !is null) display.removeWidget (fixedHandle); 150 auto imHandle = imHandle (); 151 if (imHandle !is null) display.removeWidget (cast(GtkWidget*)imHandle); 152 } 153 154 bool drawGripper (int x, int y, int width, int height, bool vertical) { 155 auto paintHandle = paintHandle (); 156 auto window = OS.GTK_WIDGET_WINDOW (paintHandle); 157 if (window is null) return false; 158 int orientation = vertical ? OS.GTK_ORIENTATION_HORIZONTAL : OS.GTK_ORIENTATION_VERTICAL; 159 if ((style & SWT.MIRRORED) !is 0) x = getClientWidth () - width - x; 160 char dummy; 161 OS.gtk_paint_handle (OS.gtk_widget_get_style (paintHandle), window, OS.GTK_STATE_NORMAL, OS.GTK_SHADOW_OUT, null, paintHandle, &dummy, x, y, width, height, orientation); 162 return true; 163 } 164 165 void enableWidget (bool enabled) { 166 OS.gtk_widget_set_sensitive (handle, enabled); 167 } 168 169 GtkWidget* enterExitHandle () { 170 return eventHandle (); 171 } 172 173 GtkWidget* eventHandle () { 174 return handle; 175 } 176 177 GdkWindow* eventWindow () { 178 auto eventHandle = eventHandle (); 179 OS.gtk_widget_realize (eventHandle); 180 return OS.GTK_WIDGET_WINDOW (eventHandle); 181 } 182 183 void fixFocus (Control focusControl) { 184 Shell shell = getShell (); 185 Control control = this; 186 while (control !is shell && (control = control.parent) !is null) { 187 if (control.setFocus ()) return; 188 } 189 shell.setSavedFocus (focusControl); 190 auto focusHandle_ = shell.vboxHandle; 191 OS.GTK_WIDGET_SET_FLAGS (focusHandle_, OS.GTK_CAN_FOCUS); 192 OS.gtk_widget_grab_focus (focusHandle_); 193 OS.GTK_WIDGET_UNSET_FLAGS (focusHandle_, OS.GTK_CAN_FOCUS); 194 } 195 196 public void fixStyle () { 197 if (fixedHandle !is null) fixStyle (fixedHandle); 198 } 199 200 void fixStyle (GtkWidget* handle) { 201 /* 202 * Feature in GTK. Some GTK themes apply a different background to 203 * the contents of a GtkNotebook. However, in an SWT TabFolder, the 204 * children are not parented below the GtkNotebook widget, and usually 205 * have their own GtkFixed. The fix is to look up the correct style 206 * for a child of a GtkNotebook and apply its background to any GtkFixed 207 * widgets that are direct children of an SWT TabFolder. 208 * 209 * Note that this has to be when the theme settings changes and that it 210 * should not override the application background. 211 */ 212 if ((state & BACKGROUND) !is 0) return; 213 auto childStyle = parent.childStyle (); 214 if (childStyle !is null) { 215 GdkColor color; 216 OS.gtk_style_get_bg (childStyle, 0, &color); 217 OS.gtk_widget_modify_bg (handle, 0, &color); 218 } 219 } 220 221 GtkWidget* focusHandle () { 222 return handle; 223 } 224 225 GtkWidget* fontHandle () { 226 return handle; 227 } 228 229 bool hasFocus () { 230 return this is display.getFocusControl(); 231 } 232 233 override void hookEvents () { 234 /* Connect the keyboard signals */ 235 auto focusHandle_ = focusHandle (); 236 int focusMask = OS.GDK_KEY_PRESS_MASK | OS.GDK_KEY_RELEASE_MASK | OS.GDK_FOCUS_CHANGE_MASK; 237 OS.gtk_widget_add_events (focusHandle_, focusMask); 238 OS.g_signal_connect_closure_by_id (focusHandle_, display.signalIds [POPUP_MENU], 0, display.closures [POPUP_MENU], false); 239 OS.g_signal_connect_closure_by_id (focusHandle_, display.signalIds [SHOW_HELP], 0, display.closures [SHOW_HELP], false); 240 OS.g_signal_connect_closure_by_id (focusHandle_, display.signalIds [KEY_PRESS_EVENT], 0, display.closures [KEY_PRESS_EVENT], false); 241 OS.g_signal_connect_closure_by_id (focusHandle_, display.signalIds [KEY_RELEASE_EVENT], 0, display.closures [KEY_RELEASE_EVENT], false); 242 OS.g_signal_connect_closure_by_id (focusHandle_, display.signalIds [FOCUS], 0, display.closures [FOCUS], false); 243 OS.g_signal_connect_closure_by_id (focusHandle_, display.signalIds [FOCUS_IN_EVENT], 0, display.closures [FOCUS_IN_EVENT], false); 244 OS.g_signal_connect_closure_by_id (focusHandle_, display.signalIds [FOCUS_OUT_EVENT], 0, display.closures [FOCUS_OUT_EVENT], false); 245 246 /* Connect the mouse signals */ 247 auto eventHandle = eventHandle (); 248 int eventMask = OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK; 249 OS.gtk_widget_add_events (eventHandle, eventMask); 250 OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.closures [BUTTON_PRESS_EVENT], false); 251 OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_RELEASE_EVENT], 0, display.closures [BUTTON_RELEASE_EVENT], false); 252 OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [MOTION_NOTIFY_EVENT], 0, display.closures [MOTION_NOTIFY_EVENT], false); 253 OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [SCROLL_EVENT], 0, display.closures [SCROLL_EVENT], false); 254 255 /* Connect enter/exit signals */ 256 auto enterExitHandle = enterExitHandle (); 257 int enterExitMask = OS.GDK_ENTER_NOTIFY_MASK | OS.GDK_LEAVE_NOTIFY_MASK; 258 OS.gtk_widget_add_events (enterExitHandle, enterExitMask); 259 OS.g_signal_connect_closure_by_id (enterExitHandle, display.signalIds [ENTER_NOTIFY_EVENT], 0, display.closures [ENTER_NOTIFY_EVENT], false); 260 OS.g_signal_connect_closure_by_id (enterExitHandle, display.signalIds [LEAVE_NOTIFY_EVENT], 0, display.closures [LEAVE_NOTIFY_EVENT], false); 261 262 /* 263 * Feature in GTK. Events such as mouse move are propagate up 264 * the widget hierarchy and are seen by the parent. This is the 265 * correct GTK behavior but not correct for SWT. The fix is to 266 * hook a signal after and stop the propagation using a negative 267 * event number to distinguish this case. 268 * 269 * The signal is hooked to the fixedHandle to catch events sent to 270 * lightweight widgets. 271 */ 272 auto blockHandle = fixedHandle !is null ? fixedHandle : eventHandle; 273 OS.g_signal_connect_closure_by_id (blockHandle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.closures [BUTTON_PRESS_EVENT_INVERSE], true); 274 OS.g_signal_connect_closure_by_id (blockHandle, display.signalIds [BUTTON_RELEASE_EVENT], 0, display.closures [BUTTON_RELEASE_EVENT_INVERSE], true); 275 OS.g_signal_connect_closure_by_id (blockHandle, display.signalIds [MOTION_NOTIFY_EVENT], 0, display.closures [MOTION_NOTIFY_EVENT_INVERSE], true); 276 277 /* Connect the event_after signal for both key and mouse */ 278 OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [EVENT_AFTER], 0, display.closures [EVENT_AFTER], false); 279 if (focusHandle_ !is eventHandle) { 280 OS.g_signal_connect_closure_by_id (focusHandle_, display.signalIds [EVENT_AFTER], 0, display.closures [EVENT_AFTER], false); 281 } 282 283 /* Connect the paint signal */ 284 auto paintHandle = paintHandle (); 285 int paintMask = OS.GDK_EXPOSURE_MASK | OS.GDK_VISIBILITY_NOTIFY_MASK; 286 OS.gtk_widget_add_events (paintHandle, paintMask); 287 OS.g_signal_connect_closure_by_id (paintHandle, display.signalIds [EXPOSE_EVENT], 0, display.closures [EXPOSE_EVENT_INVERSE], false); 288 OS.g_signal_connect_closure_by_id (paintHandle, display.signalIds [VISIBILITY_NOTIFY_EVENT], 0, display.closures [VISIBILITY_NOTIFY_EVENT], false); 289 OS.g_signal_connect_closure_by_id (paintHandle, display.signalIds [EXPOSE_EVENT], 0, display.closures [EXPOSE_EVENT], true); 290 291 /* Connect the Input Method signals */ 292 OS.g_signal_connect_closure_by_id (handle, display.signalIds [REALIZE], 0, display.closures [REALIZE], true); 293 OS.g_signal_connect_closure_by_id (handle, display.signalIds [UNREALIZE], 0, display.closures [UNREALIZE], false); 294 auto imHandle = imHandle (); 295 if (imHandle !is null) { 296 OS.g_signal_connect_closure (imHandle, OS.commit.ptr, display.closures [COMMIT], false); 297 OS.g_signal_connect_closure (imHandle, OS.preedit_changed.ptr, display.closures [PREEDIT_CHANGED], false); 298 } 299 300 OS.g_signal_connect_closure_by_id (paintHandle, display.signalIds [STYLE_SET], 0, display.closures [STYLE_SET], false); 301 302 auto topHandle_ = topHandle (); 303 OS.g_signal_connect_closure_by_id (topHandle_, display.signalIds [MAP], 0, display.closures [MAP], true); 304 } 305 306 override int hoverProc (GtkWidget* widget) { 307 int x, y; 308 int mask; 309 OS.gdk_window_get_pointer (null, &x, &y, &mask); 310 sendMouseEvent (SWT.MouseHover, 0, /*time*/0, x , y , false, mask ); 311 /* Always return zero in order to cancel the hover timer */ 312 return 0; 313 } 314 315 override GtkWidget* topHandle() { 316 if (fixedHandle !is null) return fixedHandle; 317 return super.topHandle (); 318 } 319 320 GtkWidget* paintHandle () { 321 auto topHandle_ = topHandle (); 322 auto paintHandle = handle; 323 while (paintHandle !is topHandle_) { 324 if ((OS.GTK_WIDGET_FLAGS (paintHandle) & OS.GTK_NO_WINDOW) is 0) break; 325 paintHandle = OS.gtk_widget_get_parent (paintHandle); 326 } 327 return paintHandle; 328 } 329 330 override GdkWindow* paintWindow () { 331 auto paintHandle = paintHandle (); 332 OS.gtk_widget_realize (paintHandle); 333 return OS.GTK_WIDGET_WINDOW (paintHandle); 334 } 335 336 /** 337 * Prints the receiver and all children. 338 * 339 * @param gc the gc where the drawing occurs 340 * @return <code>true</code> if the operation was successful and <code>false</code> otherwise 341 * 342 * @exception IllegalArgumentException <ul> 343 * <li>ERROR_NULL_ARGUMENT - if the gc is null</li> 344 * <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li> 345 * </ul> 346 * @exception SWTException <ul> 347 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 348 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 349 * </ul> 350 * 351 * @since 3.4 352 */ 353 public bool print (GC gc) { 354 checkWidget (); 355 if (gc is null) error (SWT.ERROR_NULL_ARGUMENT); 356 if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); 357 auto topHandle_ = topHandle (); 358 OS.gtk_widget_realize (topHandle_); 359 auto window = OS.GTK_WIDGET_WINDOW (topHandle_); 360 GCData data = gc.getGCData (); 361 OS.gdk_window_process_updates (window, cast(int)true); 362 printWidget (gc, data.drawable, OS.gdk_drawable_get_depth (data.drawable), 0, 0); 363 return true; 364 } 365 366 void printWidget (GC gc, GdkDrawable* drawable, int depth, int x, int y) { 367 bool obscured = (state & OBSCURED) !is 0; 368 state &= ~OBSCURED; 369 auto topHandle_ = topHandle (); 370 auto window = OS.GTK_WIDGET_WINDOW (topHandle_); 371 printWindow (true, this, gc.handle, drawable, depth, window, x, y); 372 if (obscured) state |= OBSCURED; 373 } 374 375 void printWindow (bool first, Control control, GdkGC* gc, GdkDrawable* drawable, int depth, GdkDrawable* window, int x, int y) { 376 if (OS.gdk_drawable_get_depth (window) !is depth) return; 377 GdkRectangle rect; 378 int width, height; 379 OS.gdk_drawable_get_size (window, &width, &height); 380 rect.width = width; 381 rect.height = height; 382 OS.gdk_window_begin_paint_rect (window, &rect); 383 GdkDrawable* real_drawable; 384 int x_offset, y_offset; 385 OS.gdk_window_get_internal_paint_info (window, &real_drawable, &x_offset, &y_offset); 386 void* userData; 387 OS.gdk_window_get_user_data (window, &userData); 388 if (userData !is null) { 389 GdkEventExpose* event = cast(GdkEventExpose*) OS.gdk_event_new (OS.GDK_EXPOSE); 390 event.type = OS.GDK_EXPOSE; 391 event.window = cast(GdkDrawable*)OS.g_object_ref (window); 392 event.area.width = rect.width; 393 event.area.height = rect.height; 394 event.region = OS.gdk_region_rectangle (&rect); 395 OS.gtk_widget_send_expose (userData, cast(GdkEvent*)event); 396 OS.gdk_event_free (cast(GdkEvent*)event); 397 } 398 int srcX = x_offset, srcY = y_offset; 399 int destX = x, destY = y, destWidth = width, destHeight = height; 400 if (!first) { 401 int cX, cY; 402 OS.gdk_window_get_position (window, &cX, &cY); 403 auto parentWindow = OS.gdk_window_get_parent (window); 404 int pW, pH; 405 OS.gdk_drawable_get_size (parentWindow, &pW, &pH); 406 srcX = x_offset - cX; 407 srcY = y_offset - cY; 408 destX = x - cX; 409 destY = y - cY; 410 destWidth = Math.min (cX + width, pW); 411 destHeight = Math.min (cY + height, pH); 412 } 413 OS.gdk_draw_drawable (drawable, gc, real_drawable, srcX, srcY, destX, destY, destWidth, destHeight); 414 OS.gdk_window_end_paint (window); 415 auto children = OS.gdk_window_get_children (window); 416 if (children !is null) { 417 auto windows = children; 418 while (windows !is null) { 419 auto child = cast(GdkDrawable*) OS.g_list_data (windows); 420 if (OS.gdk_window_is_visible (child)) { 421 void* data; 422 OS.gdk_window_get_user_data (child, &data); 423 if (data !is null) { 424 Widget widget = display.findWidget ( cast(GtkWidget*) data); 425 if (widget is null || widget is control) { 426 int x_pos, y_pos; 427 OS.gdk_window_get_position (child, &x_pos, &y_pos); 428 printWindow (false, control, gc, drawable, depth, child, x + x_pos, y + y_pos); 429 } 430 } 431 } 432 windows = OS.g_list_next (windows); 433 } 434 OS.g_list_free (children); 435 } 436 } 437 438 /** 439 * Returns the preferred size of the receiver. 440 * <p> 441 * The <em>preferred size</em> of a control is the size that it would 442 * best be displayed at. The width hint and height hint arguments 443 * allow the caller to ask a control questions such as "Given a particular 444 * width, how high does the control need to be to show all of the contents?" 445 * To indicate that the caller does not wish to constrain a particular 446 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint. 447 * </p> 448 * 449 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>) 450 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>) 451 * @return the preferred size of the control 452 * 453 * @exception SWTException <ul> 454 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 455 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 456 * </ul> 457 * 458 * @see Layout 459 * @see #getBorderWidth 460 * @see #getBounds 461 * @see #getSize 462 * @see #pack(bool) 463 * @see "computeTrim, getClientArea for controls that implement them" 464 */ 465 public Point computeSize (int wHint, int hHint) { 466 return computeSize (wHint, hHint, true); 467 } 468 469 Control computeTabGroup () { 470 if (isTabGroup()) return this; 471 return parent.computeTabGroup (); 472 } 473 474 Control[] computeTabList() { 475 if (isTabGroup()) { 476 if (getVisible() && getEnabled()) { 477 return [this]; 478 } 479 } 480 return new Control[0]; 481 } 482 483 Control computeTabRoot () { 484 Control[] tabList = parent._getTabList(); 485 if (tabList !is null) { 486 int index = 0; 487 while (index < tabList.length) { 488 if (tabList [index] is this) break; 489 index++; 490 } 491 if (index is tabList.length) { 492 if (isTabGroup ()) return this; 493 } 494 } 495 return parent.computeTabRoot (); 496 } 497 498 void checkBuffered () { 499 style |= SWT.DOUBLE_BUFFERED; 500 } 501 502 void checkBackground () { 503 Shell shell = getShell (); 504 if (this is shell) return; 505 state &= ~PARENT_BACKGROUND; 506 Composite composite = parent; 507 do { 508 int mode = composite.backgroundMode; 509 if (mode !is SWT.INHERIT_NONE) { 510 if (mode is SWT.INHERIT_DEFAULT) { 511 Control control = this; 512 do { 513 if ((control.state & THEME_BACKGROUND) is 0) { 514 return; 515 } 516 control = control.parent; 517 } while (control !is composite); 518 } 519 state |= PARENT_BACKGROUND; 520 return; 521 } 522 if (composite is shell) break; 523 composite = composite.parent; 524 } while (true); 525 } 526 527 void checkBorder () { 528 if (getBorderWidth () is 0) style &= ~SWT.BORDER; 529 } 530 531 void checkMirrored () { 532 if ((style & SWT.RIGHT_TO_LEFT) !is 0) style |= SWT.MIRRORED; 533 } 534 535 GtkStyle* childStyle () { 536 return parent.childStyle (); 537 } 538 539 override void createWidget (int index) { 540 state |= DRAG_DETECT; 541 checkOrientation (parent); 542 super.createWidget (index); 543 checkBackground (); 544 if ((state & PARENT_BACKGROUND) !is 0) setBackground (); 545 checkBuffered (); 546 showWidget (); 547 setInitialBounds (); 548 setZOrder (null, false, false); 549 setRelations (); 550 checkMirrored (); 551 checkBorder (); 552 } 553 554 /** 555 * Returns the preferred size of the receiver. 556 * <p> 557 * The <em>preferred size</em> of a control is the size that it would 558 * best be displayed at. The width hint and height hint arguments 559 * allow the caller to ask a control questions such as "Given a particular 560 * width, how high does the control need to be to show all of the contents?" 561 * To indicate that the caller does not wish to constrain a particular 562 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint. 563 * </p><p> 564 * If the changed flag is <code>true</code>, it indicates that the receiver's 565 * <em>contents</em> have changed, therefore any caches that a layout manager 566 * containing the control may have been keeping need to be flushed. When the 567 * control is resized, the changed flag will be <code>false</code>, so layout 568 * manager caches can be retained. 569 * </p> 570 * 571 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>) 572 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>) 573 * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise 574 * @return the preferred size of the control. 575 * 576 * @exception SWTException <ul> 577 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 578 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 579 * </ul> 580 * 581 * @see Layout 582 * @see #getBorderWidth 583 * @see #getBounds 584 * @see #getSize 585 * @see #pack(bool) 586 * @see "computeTrim, getClientArea for controls that implement them" 587 */ 588 public Point computeSize (int wHint, int hHint, bool changed) { 589 checkWidget(); 590 if (wHint !is SWT.DEFAULT && wHint < 0) wHint = 0; 591 if (hHint !is SWT.DEFAULT && hHint < 0) hHint = 0; 592 return computeNativeSize (handle, wHint, hHint, changed); 593 } 594 595 Point computeNativeSize (GtkWidget* h, int wHint, int hHint, bool changed) { 596 int width = wHint, height = hHint; 597 if (wHint is SWT.DEFAULT && hHint is SWT.DEFAULT) { 598 GtkRequisition requisition; 599 gtk_widget_size_request (h, &requisition); 600 width = OS.GTK_WIDGET_REQUISITION_WIDTH (h); 601 height = OS.GTK_WIDGET_REQUISITION_HEIGHT (h); 602 } else if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) { 603 int reqWidth, reqHeight; 604 OS.gtk_widget_get_size_request (h, &reqWidth, &reqHeight); 605 OS.gtk_widget_set_size_request (h, wHint, hHint); 606 GtkRequisition requisition; 607 gtk_widget_size_request (h, &requisition); 608 OS.gtk_widget_set_size_request (h, reqWidth, reqHeight); 609 width = wHint is SWT.DEFAULT ? requisition.width : wHint; 610 height = hHint is SWT.DEFAULT ? requisition.height : hHint; 611 } 612 return new Point (width, height); 613 } 614 615 void forceResize () { 616 /* 617 * Force size allocation on all children of this widget's 618 * topHandle. Note that all calls to gtk_widget_size_allocate() 619 * must be preceded by a call to gtk_widget_size_request(). 620 */ 621 auto topHandle_ = topHandle (); 622 GtkRequisition requisition; 623 gtk_widget_size_request (topHandle_, &requisition); 624 GtkAllocation allocation; 625 allocation.x = OS.GTK_WIDGET_X (topHandle_); 626 allocation.y = OS.GTK_WIDGET_Y (topHandle_); 627 allocation.width = OS.GTK_WIDGET_WIDTH (topHandle_); 628 allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle_); 629 OS.gtk_widget_size_allocate (topHandle_, &allocation); 630 } 631 632 /** 633 * Returns the accessible object for the receiver. 634 * If this is the first time this object is requested, 635 * then the object is created and returned. 636 * 637 * @return the accessible object 638 * 639 * @exception SWTException <ul> 640 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 641 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 642 * </ul> 643 * 644 * @see Accessible#addAccessibleListener 645 * @see Accessible#addAccessibleControlListener 646 * 647 * @since 2.0 648 */ 649 public Accessible getAccessible () { 650 checkWidget (); 651 if (accessible is null) { 652 accessible = Accessible.internal_new_Accessible (this); 653 } 654 return accessible; 655 } 656 657 /** 658 * Returns a rectangle describing the receiver's size and location 659 * relative to its parent (or its display if its parent is null), 660 * unless the receiver is a shell. In this case, the location is 661 * relative to the display. 662 * 663 * @return the receiver's bounding rectangle 664 * 665 * @exception SWTException <ul> 666 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 667 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 668 * </ul> 669 */ 670 public Rectangle getBounds () { 671 checkWidget(); 672 auto topHandle_ = topHandle (); 673 int x = OS.GTK_WIDGET_X (topHandle_); 674 int y = OS.GTK_WIDGET_Y (topHandle_); 675 int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); 676 int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_); 677 if ((parent.style & SWT.MIRRORED) !is 0) x = parent.getClientWidth () - width - x; 678 return new Rectangle (x, y, width, height); 679 } 680 681 /** 682 * Sets the receiver's size and location to the rectangular 683 * area specified by the argument. The <code>x</code> and 684 * <code>y</code> fields of the rectangle are relative to 685 * the receiver's parent (or its display if its parent is null). 686 * <p> 687 * Note: Attempting to set the width or height of the 688 * receiver to a negative number will cause that 689 * value to be set to zero instead. 690 * </p> 691 * 692 * @param rect the new bounds for the receiver 693 * 694 * @exception SWTException <ul> 695 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 696 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 697 * </ul> 698 */ 699 public void setBounds (Rectangle rect) { 700 checkWidget (); 701 if (rect is null) error (SWT.ERROR_NULL_ARGUMENT); 702 setBounds (rect.x, rect.y, Math.max (0, rect.width), Math.max (0, rect.height), true, true); 703 } 704 705 /** 706 * Sets the receiver's size and location to the rectangular 707 * area specified by the arguments. The <code>x</code> and 708 * <code>y</code> arguments are relative to the receiver's 709 * parent (or its display if its parent is null), unless 710 * the receiver is a shell. In this case, the <code>x</code> 711 * and <code>y</code> arguments are relative to the display. 712 * <p> 713 * Note: Attempting to set the width or height of the 714 * receiver to a negative number will cause that 715 * value to be set to zero instead. 716 * </p> 717 * 718 * @param x the new x coordinate for the receiver 719 * @param y the new y coordinate for the receiver 720 * @param width the new width for the receiver 721 * @param height the new height for the receiver 722 * 723 * @exception SWTException <ul> 724 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 725 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 726 * </ul> 727 */ 728 public void setBounds (int x, int y, int width, int height) { 729 checkWidget(); 730 setBounds (x, y, Math.max (0, width), Math.max (0, height), true, true); 731 } 732 733 void markLayout (bool changed, bool all) { 734 /* Do nothing */ 735 } 736 737 override void modifyStyle (GtkWidget* handle, GtkRcStyle* style) { 738 super.modifyStyle(handle, style); 739 /* 740 * Bug in GTK. When changing the style of a control that 741 * has had a region set on it, the region is lost. The 742 * fix is to set the region again. 743 */ 744 if (region !is null) OS.gdk_window_shape_combine_region (OS.GTK_WIDGET_WINDOW (topHandle ()), region.handle, 0, 0); 745 } 746 747 void moveHandle (int x, int y) { 748 auto topHandle_ = topHandle (); 749 auto parentHandle = parent.parentingHandle (); 750 /* 751 * Feature in GTK. Calling gtk_fixed_move() to move a child causes 752 * the whole parent to redraw. This is a performance problem. The 753 * fix is temporarily make the parent not visible during the move. 754 * 755 * NOTE: Because every widget in SWT has an X window, the new and 756 * old bounds of the child are correctly redrawn. 757 */ 758 int flags = OS.GTK_WIDGET_FLAGS (parentHandle); 759 OS.GTK_WIDGET_UNSET_FLAGS (parentHandle, OS.GTK_VISIBLE); 760 OS.gtk_fixed_move (cast(GtkFixed*)parentHandle, topHandle_, x, y); 761 if ((flags & OS.GTK_VISIBLE) !is 0) { 762 OS.GTK_WIDGET_SET_FLAGS (parentHandle, OS.GTK_VISIBLE); 763 } 764 } 765 766 void resizeHandle (int width, int height) { 767 auto topHandle_ = topHandle (); 768 OS.gtk_widget_set_size_request (topHandle_, width, height); 769 if (topHandle_ !is handle) OS.gtk_widget_set_size_request (handle, width, height); 770 } 771 772 int setBounds (int x, int y, int width, int height, bool move, bool resize) { 773 auto topHandle_ = topHandle (); 774 bool sendMove = move; 775 if ((parent.style & SWT.MIRRORED) !is 0) { 776 int clientWidth = parent.getClientWidth (); 777 int oldWidth = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); 778 int oldX = clientWidth - oldWidth - OS.GTK_WIDGET_X (topHandle_); 779 if (move) { 780 sendMove &= x !is oldX; 781 x = clientWidth - (resize ? width : oldWidth) - x; 782 } else { 783 move = true; 784 x = clientWidth - (resize ? width : oldWidth) - oldX; 785 y = OS.GTK_WIDGET_Y (topHandle_); 786 } 787 } 788 bool sameOrigin = true, sameExtent = true; 789 if (move) { 790 int oldX = OS.GTK_WIDGET_X (topHandle_); 791 int oldY = OS.GTK_WIDGET_Y (topHandle_); 792 sameOrigin = x is oldX && y is oldY; 793 if (!sameOrigin) { 794 if (enableWindow !is null) { 795 OS.gdk_window_move (enableWindow, x, y); 796 } 797 moveHandle (x, y); 798 } 799 } 800 int clientWidth = 0; 801 if (resize) { 802 int oldWidth = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); 803 int oldHeight = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_); 804 sameExtent = width is oldWidth && height is oldHeight; 805 if (!sameExtent && (style & SWT.MIRRORED) !is 0) clientWidth = getClientWidth (); 806 if (!sameExtent && !(width is 0 && height is 0)) { 807 int newWidth = Math.max (1, width); 808 int newHeight = Math.max (1, height); 809 if (redrawWindow !is null) { 810 OS.gdk_window_resize (redrawWindow, newWidth, newHeight); 811 } 812 if (enableWindow !is null) { 813 OS.gdk_window_resize (enableWindow, newWidth, newHeight); 814 } 815 resizeHandle (newWidth, newHeight); 816 } 817 } 818 if (!sameOrigin || !sameExtent) { 819 /* 820 * Cause a size allocation this widget's topHandle. Note that 821 * all calls to gtk_widget_size_allocate() must be preceded by 822 * a call to gtk_widget_size_request(). 823 */ 824 GtkRequisition requisition; 825 gtk_widget_size_request (topHandle_, &requisition); 826 GtkAllocation allocation; 827 if (move) { 828 allocation.x = x; 829 allocation.y = y; 830 } else { 831 allocation.x = OS.GTK_WIDGET_X (topHandle_); 832 allocation.y = OS.GTK_WIDGET_Y (topHandle_); 833 } 834 if (resize) { 835 allocation.width = width; 836 allocation.height = height; 837 } else { 838 allocation.width = OS.GTK_WIDGET_WIDTH (topHandle_); 839 allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle_); 840 } 841 OS.gtk_widget_size_allocate (topHandle_, &allocation); 842 } 843 /* 844 * Bug in GTK. Widgets cannot be sized smaller than 1x1. 845 * The fix is to hide zero-sized widgets and show them again 846 * when they are resized larger. 847 */ 848 if (!sameExtent) { 849 state = (width is 0) ? state | ZERO_WIDTH : state & ~ZERO_WIDTH; 850 state = (height is 0) ? state | ZERO_HEIGHT : state & ~ZERO_HEIGHT; 851 if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) !is 0) { 852 if (enableWindow !is null) { 853 OS.gdk_window_hide (enableWindow); 854 } 855 OS.gtk_widget_hide (topHandle_); 856 } else { 857 if ((state & HIDDEN) is 0) { 858 if (enableWindow !is null) { 859 OS.gdk_window_show_unraised (enableWindow); 860 } 861 OS.gtk_widget_show (topHandle_); 862 } 863 } 864 if ((style & SWT.MIRRORED) !is 0) moveChildren (clientWidth); 865 } 866 int result = 0; 867 if (move && !sameOrigin) { 868 Control control = findBackgroundControl (); 869 if (control !is null && control.backgroundImage !is null) { 870 if (isVisible ()) redrawWidget (0, 0, 0, 0, true, true, true); 871 } 872 if (sendMove) sendEvent (SWT.Move); 873 result |= MOVED; 874 } 875 if (resize && !sameExtent) { 876 sendEvent (SWT.Resize); 877 result |= RESIZED; 878 } 879 return result; 880 } 881 882 /** 883 * Returns a point describing the receiver's location relative 884 * to its parent (or its display if its parent is null), unless 885 * the receiver is a shell. In this case, the point is 886 * relative to the display. 887 * 888 * @return the receiver's location 889 * 890 * @exception SWTException <ul> 891 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 892 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 893 * </ul> 894 */ 895 public Point getLocation () { 896 checkWidget(); 897 auto topHandle_ = topHandle (); 898 int x = OS.GTK_WIDGET_X (topHandle_); 899 int y = OS.GTK_WIDGET_Y (topHandle_); 900 if ((parent.style & SWT.MIRRORED) !is 0) { 901 int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); 902 x = parent.getClientWidth () - width - x; 903 } 904 return new Point (x, y); 905 } 906 907 /** 908 * Sets the receiver's location to the point specified by 909 * the arguments which are relative to the receiver's 910 * parent (or its display if its parent is null), unless 911 * the receiver is a shell. In this case, the point is 912 * relative to the display. 913 * 914 * @param location the new location for the receiver 915 * 916 * @exception SWTException <ul> 917 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 918 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 919 * </ul> 920 */ 921 public void setLocation (Point location) { 922 checkWidget (); 923 if (location is null) error (SWT.ERROR_NULL_ARGUMENT); 924 setBounds (location.x, location.y, 0, 0, true, false); 925 } 926 927 /** 928 * Sets the receiver's location to the point specified by 929 * the arguments which are relative to the receiver's 930 * parent (or its display if its parent is null), unless 931 * the receiver is a shell. In this case, the point is 932 * relative to the display. 933 * 934 * @param x the new x coordinate for the receiver 935 * @param y the new y coordinate for the receiver 936 * 937 * @exception SWTException <ul> 938 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 939 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 940 * </ul> 941 */ 942 public void setLocation(int x, int y) { 943 checkWidget(); 944 setBounds (x, y, 0, 0, true, false); 945 } 946 947 /** 948 * Returns a point describing the receiver's size. The 949 * x coordinate of the result is the width of the receiver. 950 * The y coordinate of the result is the height of the 951 * receiver. 952 * 953 * @return the receiver's size 954 * 955 * @exception SWTException <ul> 956 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 957 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 958 * </ul> 959 */ 960 public Point getSize () { 961 checkWidget(); 962 auto topHandle_ = topHandle (); 963 int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); 964 int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_); 965 return new Point (width, height); 966 } 967 968 /** 969 * Sets the receiver's size to the point specified by the argument. 970 * <p> 971 * Note: Attempting to set the width or height of the 972 * receiver to a negative number will cause them to be 973 * set to zero instead. 974 * </p> 975 * 976 * @param size the new size for the receiver 977 * 978 * @exception IllegalArgumentException <ul> 979 * <li>ERROR_NULL_ARGUMENT - if the point is null</li> 980 * </ul> 981 * @exception SWTException <ul> 982 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 983 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 984 * </ul> 985 */ 986 public void setSize (Point size) { 987 checkWidget (); 988 if (size is null) error (SWT.ERROR_NULL_ARGUMENT); 989 setBounds (0, 0, Math.max (0, size.x), Math.max (0, size.y), false, true); 990 } 991 992 /** 993 * Sets the shape of the control to the region specified 994 * by the argument. When the argument is null, the 995 * default shape of the control is restored. 996 * 997 * @param region the region that defines the shape of the control (or null) 998 * 999 * @exception IllegalArgumentException <ul> 1000 * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li> 1001 * </ul> 1002 * @exception SWTException <ul> 1003 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1004 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1005 * </ul> 1006 * 1007 * @since 3.4 1008 */ 1009 public void setRegion (Region region) { 1010 checkWidget (); 1011 if (region !is null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); 1012 auto window = OS.GTK_WIDGET_WINDOW (topHandle ()); 1013 auto shape_region = (region is null) ? null : region.handle; 1014 OS.gdk_window_shape_combine_region (window, shape_region, 0, 0); 1015 this.region = region; 1016 } 1017 1018 void setRelations () { 1019 auto parentHandle = parent.parentingHandle (); 1020 auto list = OS.gtk_container_get_children (cast(GtkContainer*)parentHandle); 1021 if (list is null) return; 1022 int count = OS.g_list_length (list); 1023 if (count > 1) { 1024 /* 1025 * the receiver is the last item in the list, so its predecessor will 1026 * be the second-last item in the list 1027 */ 1028 auto handle = cast(GtkWidget*) OS.g_list_nth_data (list, count - 2); 1029 if (handle !is null) { 1030 Widget widget = display.getWidget (handle); 1031 if (widget !is null && widget !is this) { 1032 if (auto sibling = cast(Control)widget ) { 1033 sibling.addRelation (this); 1034 } 1035 } 1036 } 1037 } 1038 OS.g_list_free (list); 1039 } 1040 1041 /** 1042 * Sets the receiver's size to the point specified by the arguments. 1043 * <p> 1044 * Note: Attempting to set the width or height of the 1045 * receiver to a negative number will cause that 1046 * value to be set to zero instead. 1047 * </p> 1048 * 1049 * @param width the new width for the receiver 1050 * @param height the new height for the receiver 1051 * 1052 * @exception SWTException <ul> 1053 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1054 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1055 * </ul> 1056 */ 1057 public void setSize (int width, int height) { 1058 checkWidget(); 1059 setBounds (0, 0, Math.max (0, width), Math.max (0, height), false, true); 1060 } 1061 1062 /* 1063 * Answers a bool indicating whether a Label that precedes the receiver in 1064 * a layout should be read by screen readers as the recevier's label. 1065 */ 1066 bool isDescribedByLabel () { 1067 return true; 1068 } 1069 1070 bool isFocusHandle (GtkWidget* widget) { 1071 return widget is focusHandle (); 1072 } 1073 1074 /** 1075 * Moves the receiver above the specified control in the 1076 * drawing order. If the argument is null, then the receiver 1077 * is moved to the top of the drawing order. The control at 1078 * the top of the drawing order will not be covered by other 1079 * controls even if they occupy intersecting areas. 1080 * 1081 * @param control the sibling control (or null) 1082 * 1083 * @exception IllegalArgumentException <ul> 1084 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li> 1085 * </ul> 1086 * @exception SWTException <ul> 1087 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1088 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1089 * </ul> 1090 * 1091 * @see Control#moveBelow 1092 * @see Composite#getChildren 1093 */ 1094 public void moveAbove (Control control) { 1095 checkWidget(); 1096 if (control !is null) { 1097 if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); 1098 if (parent !is control.parent) return; 1099 } 1100 setZOrder (control, true, true); 1101 } 1102 1103 /** 1104 * Moves the receiver below the specified control in the 1105 * drawing order. If the argument is null, then the receiver 1106 * is moved to the bottom of the drawing order. The control at 1107 * the bottom of the drawing order will be covered by all other 1108 * controls which occupy intersecting areas. 1109 * 1110 * @param control the sibling control (or null) 1111 * 1112 * @exception IllegalArgumentException <ul> 1113 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li> 1114 * </ul> 1115 * @exception SWTException <ul> 1116 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1117 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1118 * </ul> 1119 * 1120 * @see Control#moveAbove 1121 * @see Composite#getChildren 1122 */ 1123 public void moveBelow (Control control) { 1124 checkWidget(); 1125 if (control !is null) { 1126 if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT); 1127 if (parent !is control.parent) return; 1128 } 1129 setZOrder (control, false, true); 1130 } 1131 1132 void moveChildren (int oldWidth) { 1133 } 1134 1135 /** 1136 * Causes the receiver to be resized to its preferred size. 1137 * For a composite, this involves computing the preferred size 1138 * from its layout, if there is one. 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 #computeSize(int, int, bool) 1146 */ 1147 public void pack () { 1148 pack (true); 1149 } 1150 1151 /** 1152 * Causes the receiver to be resized to its preferred size. 1153 * For a composite, this involves computing the preferred size 1154 * from its layout, if there is one. 1155 * <p> 1156 * If the changed flag is <code>true</code>, it indicates that the receiver's 1157 * <em>contents</em> have changed, therefore any caches that a layout manager 1158 * containing the control may have been keeping need to be flushed. When the 1159 * control is resized, the changed flag will be <code>false</code>, so layout 1160 * manager caches can be retained. 1161 * </p> 1162 * 1163 * @param changed whether or not the receiver's contents have changed 1164 * 1165 * @exception SWTException <ul> 1166 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1167 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1168 * </ul> 1169 * 1170 * @see #computeSize(int, int, bool) 1171 */ 1172 public void pack (bool changed) { 1173 setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed)); 1174 } 1175 1176 /** 1177 * Sets the layout data associated with the receiver to the argument. 1178 * 1179 * @param layoutData the new layout data for the receiver. 1180 * 1181 * @exception SWTException <ul> 1182 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1183 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1184 * </ul> 1185 */ 1186 public void setLayoutData (Object layoutData) { 1187 checkWidget(); 1188 this.layoutData = layoutData; 1189 } 1190 1191 /** 1192 * Returns a point which is the result of converting the 1193 * argument, which is specified in display relative coordinates, 1194 * to coordinates relative to the receiver. 1195 * <p> 1196 * @param x the x coordinate to be translated 1197 * @param y the y coordinate to be translated 1198 * @return the translated coordinates 1199 * 1200 * @exception SWTException <ul> 1201 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1202 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1203 * </ul> 1204 * 1205 * @since 2.1 1206 */ 1207 public Point toControl (int x, int y) { 1208 checkWidget (); 1209 auto window = eventWindow (); 1210 int origin_x, origin_y; 1211 OS.gdk_window_get_origin (window, &origin_x, &origin_y); 1212 x -= origin_x ; 1213 y -= origin_y ; 1214 if ((style & SWT.MIRRORED) !is 0) x = getClientWidth () - x; 1215 return new Point (x, y); 1216 } 1217 1218 /** 1219 * Returns a point which is the result of converting the 1220 * argument, which is specified in display relative coordinates, 1221 * to coordinates relative to the receiver. 1222 * <p> 1223 * @param point the point to be translated (must not be null) 1224 * @return the translated coordinates 1225 * 1226 * @exception IllegalArgumentException <ul> 1227 * <li>ERROR_NULL_ARGUMENT - if the point is null</li> 1228 * </ul> 1229 * @exception SWTException <ul> 1230 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1231 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1232 * </ul> 1233 */ 1234 public Point toControl (Point point) { 1235 checkWidget (); 1236 if (point is null) error (SWT.ERROR_NULL_ARGUMENT); 1237 return toControl (point.x, point.y); 1238 } 1239 1240 /** 1241 * Returns a point which is the result of converting the 1242 * argument, which is specified in coordinates relative to 1243 * the receiver, to display relative coordinates. 1244 * <p> 1245 * @param x the x coordinate to be translated 1246 * @param y the y coordinate to be translated 1247 * @return the translated coordinates 1248 * 1249 * @exception SWTException <ul> 1250 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1251 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1252 * </ul> 1253 * 1254 * @since 2.1 1255 */ 1256 public Point toDisplay (int x, int y) { 1257 checkWidget(); 1258 auto window = eventWindow (); 1259 int origin_x, origin_y; 1260 OS.gdk_window_get_origin (window, &origin_x, &origin_y); 1261 if ((style & SWT.MIRRORED) !is 0) x = getClientWidth () - x; 1262 x += origin_x ; 1263 y += origin_y ; 1264 return new Point (x, y); 1265 } 1266 1267 /** 1268 * Returns a point which is the result of converting the 1269 * argument, which is specified in coordinates relative to 1270 * the receiver, to display relative coordinates. 1271 * <p> 1272 * @param point the point to be translated (must not be null) 1273 * @return the translated coordinates 1274 * 1275 * @exception IllegalArgumentException <ul> 1276 * <li>ERROR_NULL_ARGUMENT - if the point is null</li> 1277 * </ul> 1278 * @exception SWTException <ul> 1279 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1280 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1281 * </ul> 1282 */ 1283 public Point toDisplay (Point point) { 1284 checkWidget(); 1285 if (point is null) error (SWT.ERROR_NULL_ARGUMENT); 1286 return toDisplay (point.x, point.y); 1287 } 1288 1289 /** 1290 * Adds the listener to the collection of listeners who will 1291 * be notified when the control is moved or resized, by sending 1292 * it one of the messages defined in the <code>ControlListener</code> 1293 * interface. 1294 * 1295 * @param listener the listener which should be notified 1296 * 1297 * @exception IllegalArgumentException <ul> 1298 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1299 * </ul> 1300 * @exception SWTException <ul> 1301 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1302 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1303 * </ul> 1304 * 1305 * @see ControlListener 1306 * @see #removeControlListener 1307 */ 1308 public void addControlListener(ControlListener listener) { 1309 checkWidget(); 1310 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1311 TypedListener typedListener = new TypedListener (listener); 1312 addListener (SWT.Resize,typedListener); 1313 addListener (SWT.Move,typedListener); 1314 } 1315 1316 /** 1317 * Adds the listener to the collection of listeners who will 1318 * be notified when a drag gesture occurs, by sending it 1319 * one of the messages defined in the <code>DragDetectListener</code> 1320 * interface. 1321 * 1322 * @param listener the listener which should be notified 1323 * 1324 * @exception IllegalArgumentException <ul> 1325 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1326 * </ul> 1327 * @exception SWTException <ul> 1328 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1329 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1330 * </ul> 1331 * 1332 * @see DragDetectListener 1333 * @see #removeDragDetectListener 1334 * 1335 * @since 3.3 1336 */ 1337 public void addDragDetectListener (DragDetectListener listener) { 1338 checkWidget (); 1339 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1340 TypedListener typedListener = new TypedListener (listener); 1341 addListener (SWT.DragDetect,typedListener); 1342 } 1343 1344 /** 1345 * Adds the listener to the collection of listeners who will 1346 * be notified when the control gains or loses focus, by sending 1347 * it one of the messages defined in the <code>FocusListener</code> 1348 * interface. 1349 * 1350 * @param listener the listener which should be notified 1351 * 1352 * @exception IllegalArgumentException <ul> 1353 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1354 * </ul> 1355 * @exception SWTException <ul> 1356 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1357 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1358 * </ul> 1359 * 1360 * @see FocusListener 1361 * @see #removeFocusListener 1362 */ 1363 public void addFocusListener(FocusListener listener) { 1364 checkWidget(); 1365 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1366 TypedListener typedListener = new TypedListener (listener); 1367 addListener(SWT.FocusIn,typedListener); 1368 addListener(SWT.FocusOut,typedListener); 1369 } 1370 1371 /** 1372 * Adds the listener to the collection of listeners who will 1373 * be notified when help events are generated for the control, 1374 * by sending it one of the messages defined in the 1375 * <code>HelpListener</code> interface. 1376 * 1377 * @param listener the listener which should be notified 1378 * 1379 * @exception IllegalArgumentException <ul> 1380 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1381 * </ul> 1382 * @exception SWTException <ul> 1383 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1384 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1385 * </ul> 1386 * 1387 * @see HelpListener 1388 * @see #removeHelpListener 1389 */ 1390 public void addHelpListener (HelpListener listener) { 1391 checkWidget(); 1392 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1393 TypedListener typedListener = new TypedListener (listener); 1394 addListener (SWT.Help, typedListener); 1395 } 1396 1397 /** 1398 * Adds the listener to the collection of listeners who will 1399 * be notified when keys are pressed and released on the system keyboard, by sending 1400 * it one of the messages defined in the <code>KeyListener</code> 1401 * interface. 1402 * <p> 1403 * When a key listener is added to a control, the control 1404 * will take part in widget traversal. By default, all 1405 * traversal keys (such as the tab key and so on) are 1406 * delivered to the control. In order for a control to take 1407 * part in traversal, it should listen for traversal events. 1408 * Otherwise, the user can traverse into a control but not 1409 * out. Note that native controls such as table and tree 1410 * implement key traversal in the operating system. It is 1411 * not necessary to add traversal listeners for these controls, 1412 * unless you want to override the default traversal. 1413 * </p> 1414 * @param listener the listener which should be notified 1415 * 1416 * @exception IllegalArgumentException <ul> 1417 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1418 * </ul> 1419 * @exception SWTException <ul> 1420 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1421 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1422 * </ul> 1423 * 1424 * @see KeyListener 1425 * @see #removeKeyListener 1426 */ 1427 public void addKeyListener(KeyListener listener) { 1428 checkWidget(); 1429 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1430 TypedListener typedListener = new TypedListener (listener); 1431 addListener(SWT.KeyUp,typedListener); 1432 addListener(SWT.KeyDown,typedListener); 1433 } 1434 1435 /** 1436 * Adds the listener to the collection of listeners who will 1437 * be notified when the platform-specific context menu trigger 1438 * has occurred, by sending it one of the messages defined in 1439 * the <code>MenuDetectListener</code> interface. 1440 * 1441 * @param listener the listener which should be notified 1442 * 1443 * @exception IllegalArgumentException <ul> 1444 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1445 * </ul> 1446 * @exception SWTException <ul> 1447 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1448 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1449 * </ul> 1450 * 1451 * @see MenuDetectListener 1452 * @see #removeMenuDetectListener 1453 * 1454 * @since 3.3 1455 */ 1456 public void addMenuDetectListener (MenuDetectListener listener) { 1457 checkWidget (); 1458 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1459 TypedListener typedListener = new TypedListener (listener); 1460 addListener (SWT.MenuDetect, typedListener); 1461 } 1462 1463 /** 1464 * Adds the listener to the collection of listeners who will 1465 * be notified when mouse buttons are pressed and released, by sending 1466 * it one of the messages defined in the <code>MouseListener</code> 1467 * interface. 1468 * 1469 * @param listener the listener which should be notified 1470 * 1471 * @exception IllegalArgumentException <ul> 1472 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1473 * </ul> 1474 * @exception SWTException <ul> 1475 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1476 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1477 * </ul> 1478 * 1479 * @see MouseListener 1480 * @see #removeMouseListener 1481 */ 1482 public void addMouseListener(MouseListener listener) { 1483 checkWidget(); 1484 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1485 TypedListener typedListener = new TypedListener (listener); 1486 addListener(SWT.MouseDown,typedListener); 1487 addListener(SWT.MouseUp,typedListener); 1488 addListener(SWT.MouseDoubleClick,typedListener); 1489 } 1490 1491 /** 1492 * Adds the listener to the collection of listeners who will 1493 * be notified when the mouse moves, by sending it one of the 1494 * messages defined in the <code>MouseMoveListener</code> 1495 * interface. 1496 * 1497 * @param listener the listener which should be notified 1498 * 1499 * @exception IllegalArgumentException <ul> 1500 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1501 * </ul> 1502 * @exception SWTException <ul> 1503 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1504 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1505 * </ul> 1506 * 1507 * @see MouseMoveListener 1508 * @see #removeMouseMoveListener 1509 */ 1510 public void addMouseMoveListener(MouseMoveListener listener) { 1511 checkWidget(); 1512 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1513 TypedListener typedListener = new TypedListener (listener); 1514 addListener(SWT.MouseMove,typedListener); 1515 } 1516 1517 /** 1518 * Adds the listener to the collection of listeners who will 1519 * be notified when the mouse passes or hovers over controls, by sending 1520 * it one of the messages defined in the <code>MouseTrackListener</code> 1521 * interface. 1522 * 1523 * @param listener the listener which should be notified 1524 * 1525 * @exception IllegalArgumentException <ul> 1526 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1527 * </ul> 1528 * @exception SWTException <ul> 1529 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1530 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1531 * </ul> 1532 * 1533 * @see MouseTrackListener 1534 * @see #removeMouseTrackListener 1535 */ 1536 public void addMouseTrackListener (MouseTrackListener listener) { 1537 checkWidget(); 1538 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1539 TypedListener typedListener = new TypedListener (listener); 1540 addListener (SWT.MouseEnter,typedListener); 1541 addListener (SWT.MouseExit,typedListener); 1542 addListener (SWT.MouseHover,typedListener); 1543 } 1544 1545 /** 1546 * Adds the listener to the collection of listeners who will 1547 * be notified when the mouse wheel is scrolled, by sending 1548 * it one of the messages defined in the 1549 * <code>MouseWheelListener</code> interface. 1550 * 1551 * @param listener the listener which should be notified 1552 * 1553 * @exception IllegalArgumentException <ul> 1554 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1555 * </ul> 1556 * @exception SWTException <ul> 1557 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1558 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1559 * </ul> 1560 * 1561 * @see MouseWheelListener 1562 * @see #removeMouseWheelListener 1563 * 1564 * @since 3.3 1565 */ 1566 public void addMouseWheelListener (MouseWheelListener listener) { 1567 checkWidget (); 1568 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1569 TypedListener typedListener = new TypedListener (listener); 1570 addListener (SWT.MouseWheel, typedListener); 1571 } 1572 1573 /** 1574 * Adds the listener to the collection of listeners who will 1575 * be notified when the receiver needs to be painted, by sending it 1576 * one of the messages defined in the <code>PaintListener</code> 1577 * interface. 1578 * 1579 * @param listener the listener which should be notified 1580 * 1581 * @exception IllegalArgumentException <ul> 1582 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1583 * </ul> 1584 * @exception SWTException <ul> 1585 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1586 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1587 * </ul> 1588 * 1589 * @see PaintListener 1590 * @see #removePaintListener 1591 */ 1592 public void addPaintListener(PaintListener listener) { 1593 checkWidget(); 1594 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1595 TypedListener typedListener = new TypedListener (listener); 1596 addListener(SWT.Paint,typedListener); 1597 } 1598 1599 void addRelation (Control control) { 1600 } 1601 1602 /** 1603 * Adds the listener to the collection of listeners who will 1604 * be notified when traversal events occur, by sending it 1605 * one of the messages defined in the <code>TraverseListener</code> 1606 * interface. 1607 * 1608 * @param listener the listener which should be notified 1609 * 1610 * @exception IllegalArgumentException <ul> 1611 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1612 * </ul> 1613 * @exception SWTException <ul> 1614 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1615 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1616 * </ul> 1617 * 1618 * @see TraverseListener 1619 * @see #removeTraverseListener 1620 */ 1621 public void addTraverseListener (TraverseListener listener) { 1622 checkWidget(); 1623 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1624 TypedListener typedListener = new TypedListener (listener); 1625 addListener (SWT.Traverse,typedListener); 1626 } 1627 1628 /** 1629 * Removes the listener from the collection of listeners who will 1630 * be notified when the control is moved or resized. 1631 * 1632 * @param listener the listener which should no longer be notified 1633 * 1634 * @exception IllegalArgumentException <ul> 1635 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1636 * </ul> 1637 * @exception SWTException <ul> 1638 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1639 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1640 * </ul> 1641 * 1642 * @see ControlListener 1643 * @see #addControlListener 1644 */ 1645 public void removeControlListener (ControlListener listener) { 1646 checkWidget(); 1647 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1648 if (eventTable is null) return; 1649 eventTable.unhook (SWT.Move, listener); 1650 eventTable.unhook (SWT.Resize, listener); 1651 } 1652 1653 /** 1654 * Removes the listener from the collection of listeners who will 1655 * be notified when a drag gesture occurs. 1656 * 1657 * @param listener the listener which should no longer be notified 1658 * 1659 * @exception IllegalArgumentException <ul> 1660 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1661 * </ul> 1662 * @exception SWTException <ul> 1663 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1664 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1665 * </ul> 1666 * 1667 * @see DragDetectListener 1668 * @see #addDragDetectListener 1669 * 1670 * @since 3.3 1671 */ 1672 public void removeDragDetectListener(DragDetectListener listener) { 1673 checkWidget (); 1674 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1675 if (eventTable is null) return; 1676 eventTable.unhook (SWT.DragDetect, listener); 1677 } 1678 1679 /** 1680 * Removes the listener from the collection of listeners who will 1681 * be notified when the control gains or loses focus. 1682 * 1683 * @param listener the listener which should no longer be notified 1684 * 1685 * @exception IllegalArgumentException <ul> 1686 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1687 * </ul> 1688 * @exception SWTException <ul> 1689 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1690 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1691 * </ul> 1692 * 1693 * @see FocusListener 1694 * @see #addFocusListener 1695 */ 1696 public void removeFocusListener(FocusListener listener) { 1697 checkWidget(); 1698 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1699 if (eventTable is null) return; 1700 eventTable.unhook (SWT.FocusIn, listener); 1701 eventTable.unhook (SWT.FocusOut, listener); 1702 } 1703 /** 1704 * Removes the listener from the collection of listeners who will 1705 * be notified when the help events are generated for the control. 1706 * 1707 * @param listener the listener which should no longer be notified 1708 * 1709 * @exception IllegalArgumentException <ul> 1710 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1711 * </ul> 1712 * @exception SWTException <ul> 1713 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1714 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1715 * </ul> 1716 * 1717 * @see HelpListener 1718 * @see #addHelpListener 1719 */ 1720 public void removeHelpListener (HelpListener listener) { 1721 checkWidget(); 1722 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1723 if (eventTable is null) return; 1724 eventTable.unhook (SWT.Help, listener); 1725 } 1726 /** 1727 * Removes the listener from the collection of listeners who will 1728 * be notified when keys are pressed and released on the system keyboard. 1729 * 1730 * @param listener the listener which should no longer be notified 1731 * 1732 * @exception IllegalArgumentException <ul> 1733 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1734 * </ul> 1735 * @exception SWTException <ul> 1736 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1737 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1738 * </ul> 1739 * 1740 * @see KeyListener 1741 * @see #addKeyListener 1742 */ 1743 public void removeKeyListener(KeyListener listener) { 1744 checkWidget(); 1745 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1746 if (eventTable is null) return; 1747 eventTable.unhook (SWT.KeyUp, listener); 1748 eventTable.unhook (SWT.KeyDown, listener); 1749 } 1750 /** 1751 * Removes the listener from the collection of listeners who will 1752 * be notified when the platform-specific context menu trigger has 1753 * occurred. 1754 * 1755 * @param listener the listener which should no longer be notified 1756 * 1757 * @exception IllegalArgumentException <ul> 1758 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1759 * </ul> 1760 * @exception SWTException <ul> 1761 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1762 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1763 * </ul> 1764 * 1765 * @see MenuDetectListener 1766 * @see #addMenuDetectListener 1767 * 1768 * @since 3.3 1769 */ 1770 public void removeMenuDetectListener (MenuDetectListener listener) { 1771 checkWidget (); 1772 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1773 if (eventTable is null) return; 1774 eventTable.unhook (SWT.MenuDetect, listener); 1775 } 1776 /** 1777 * Removes the listener from the collection of listeners who will 1778 * be notified when mouse buttons are pressed and released. 1779 * 1780 * @param listener the listener which should no longer be notified 1781 * 1782 * @exception IllegalArgumentException <ul> 1783 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1784 * </ul> 1785 * @exception SWTException <ul> 1786 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1787 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1788 * </ul> 1789 * 1790 * @see MouseListener 1791 * @see #addMouseListener 1792 */ 1793 public void removeMouseListener (MouseListener listener) { 1794 checkWidget(); 1795 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1796 if (eventTable is null) return; 1797 eventTable.unhook (SWT.MouseDown, listener); 1798 eventTable.unhook (SWT.MouseUp, listener); 1799 eventTable.unhook (SWT.MouseDoubleClick, listener); 1800 } 1801 /** 1802 * Removes the listener from the collection of listeners who will 1803 * be notified when the mouse moves. 1804 * 1805 * @param listener the listener which should no longer be notified 1806 * 1807 * @exception IllegalArgumentException <ul> 1808 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1809 * </ul> 1810 * @exception SWTException <ul> 1811 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1812 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1813 * </ul> 1814 * 1815 * @see MouseMoveListener 1816 * @see #addMouseMoveListener 1817 */ 1818 public void removeMouseMoveListener(MouseMoveListener listener) { 1819 checkWidget(); 1820 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1821 if (eventTable is null) return; 1822 eventTable.unhook (SWT.MouseMove, listener); 1823 } 1824 1825 /** 1826 * Removes the listener from the collection of listeners who will 1827 * be notified when the mouse passes or hovers over controls. 1828 * 1829 * @param listener the listener which should no longer be notified 1830 * 1831 * @exception IllegalArgumentException <ul> 1832 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1833 * </ul> 1834 * @exception SWTException <ul> 1835 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1836 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1837 * </ul> 1838 * 1839 * @see MouseTrackListener 1840 * @see #addMouseTrackListener 1841 */ 1842 public void removeMouseTrackListener(MouseTrackListener listener) { 1843 checkWidget(); 1844 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1845 if (eventTable is null) return; 1846 eventTable.unhook (SWT.MouseEnter, listener); 1847 eventTable.unhook (SWT.MouseExit, listener); 1848 eventTable.unhook (SWT.MouseHover, listener); 1849 } 1850 1851 /** 1852 * Removes the listener from the collection of listeners who will 1853 * be notified when the mouse wheel is scrolled. 1854 * 1855 * @param listener the listener which should no longer be notified 1856 * 1857 * @exception IllegalArgumentException <ul> 1858 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1859 * </ul> 1860 * @exception SWTException <ul> 1861 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1862 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1863 * </ul> 1864 * 1865 * @see MouseWheelListener 1866 * @see #addMouseWheelListener 1867 * 1868 * @since 3.3 1869 */ 1870 public void removeMouseWheelListener (MouseWheelListener listener) { 1871 checkWidget (); 1872 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1873 if (eventTable is null) return; 1874 eventTable.unhook (SWT.MouseWheel, listener); 1875 } 1876 1877 /** 1878 * Removes the listener from the collection of listeners who will 1879 * be notified when the receiver needs to be painted. 1880 * 1881 * @param listener the listener which should no longer be notified 1882 * 1883 * @exception IllegalArgumentException <ul> 1884 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1885 * </ul> 1886 * @exception SWTException <ul> 1887 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1888 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1889 * </ul> 1890 * 1891 * @see PaintListener 1892 * @see #addPaintListener 1893 */ 1894 public void removePaintListener(PaintListener listener) { 1895 checkWidget(); 1896 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1897 if (eventTable is null) return; 1898 eventTable.unhook(SWT.Paint, listener); 1899 } 1900 1901 /* 1902 * Remove "Labelled by" relations from the receiver. 1903 */ 1904 void removeRelation () { 1905 if (!isDescribedByLabel ()) return; /* there will not be any */ 1906 auto accessible = OS.gtk_widget_get_accessible (handle); 1907 if (accessible is null) return; 1908 auto set = ATK.atk_object_ref_relation_set (accessible); 1909 int count = ATK.atk_relation_set_get_n_relations (set); 1910 for (int i = 0; i < count; i++) { 1911 auto relation = ATK.atk_relation_set_get_relation (set, 0); 1912 ATK.atk_relation_set_remove (set, relation); 1913 } 1914 OS.g_object_unref (set); 1915 } 1916 1917 /** 1918 * Removes the listener from the collection of listeners who will 1919 * be notified when traversal events occur. 1920 * 1921 * @param listener the listener which should no longer be notified 1922 * 1923 * @exception IllegalArgumentException <ul> 1924 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 1925 * </ul> 1926 * @exception SWTException <ul> 1927 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1928 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1929 * </ul> 1930 * 1931 * @see TraverseListener 1932 * @see #addTraverseListener 1933 */ 1934 public void removeTraverseListener(TraverseListener listener) { 1935 checkWidget (); 1936 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 1937 if (eventTable is null) return; 1938 eventTable.unhook (SWT.Traverse, listener); 1939 } 1940 1941 /** 1942 * Detects a drag and drop gesture. This method is used 1943 * to detect a drag gesture when called from within a mouse 1944 * down listener. 1945 * 1946 * <p>By default, a drag is detected when the gesture 1947 * occurs anywhere within the client area of a control. 1948 * Some controls, such as tables and trees, override this 1949 * behavior. In addition to the operating system specific 1950 * drag gesture, they require the mouse to be inside an 1951 * item. Custom widget writers can use <code>setDragDetect</code> 1952 * to disable the default detection, listen for mouse down, 1953 * and then call <code>dragDetect()</code> from within the 1954 * listener to conditionally detect a drag. 1955 * </p> 1956 * 1957 * @param event the mouse down event 1958 * 1959 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise. 1960 * 1961 * @exception IllegalArgumentException <ul> 1962 * <li>ERROR_NULL_ARGUMENT when the event is null</li> 1963 * </ul> 1964 * @exception SWTException <ul> 1965 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 1966 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 1967 * </ul> 1968 * 1969 * @see DragDetectListener 1970 * @see #addDragDetectListener 1971 * 1972 * @see #getDragDetect 1973 * @see #setDragDetect 1974 * 1975 * @since 3.3 1976 */ 1977 public bool dragDetect (Event event) { 1978 checkWidget (); 1979 if (event is null) error (SWT.ERROR_NULL_ARGUMENT); 1980 return dragDetect (event.button, event.count, event.stateMask, event.x, event.y); 1981 } 1982 1983 /** 1984 * Detects a drag and drop gesture. This method is used 1985 * to detect a drag gesture when called from within a mouse 1986 * down listener. 1987 * 1988 * <p>By default, a drag is detected when the gesture 1989 * occurs anywhere within the client area of a control. 1990 * Some controls, such as tables and trees, override this 1991 * behavior. In addition to the operating system specific 1992 * drag gesture, they require the mouse to be inside an 1993 * item. Custom widget writers can use <code>setDragDetect</code> 1994 * to disable the default detection, listen for mouse down, 1995 * and then call <code>dragDetect()</code> from within the 1996 * listener to conditionally detect a drag. 1997 * </p> 1998 * 1999 * @param event the mouse down event 2000 * 2001 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise. 2002 * 2003 * @exception IllegalArgumentException <ul> 2004 * <li>ERROR_NULL_ARGUMENT when the event is null</li> 2005 * </ul> 2006 * @exception SWTException <ul> 2007 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2008 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2009 * </ul> 2010 * 2011 * @see DragDetectListener 2012 * @see #addDragDetectListener 2013 * 2014 * @see #getDragDetect 2015 * @see #setDragDetect 2016 * 2017 * @since 3.3 2018 */ 2019 public bool dragDetect (MouseEvent event) { 2020 checkWidget (); 2021 if (event is null) error (SWT.ERROR_NULL_ARGUMENT); 2022 return dragDetect (event.button, event.count, event.stateMask, event.x, event.y); 2023 } 2024 2025 bool dragDetect (int button, int count, int stateMask, int x, int y) { 2026 if (button !is 1 || count !is 1) return false; 2027 if (!dragDetect (x, y, false, null)) return false; 2028 return sendDragEvent (button, stateMask, x, y, true); 2029 } 2030 2031 bool dragDetect (int x, int y, bool filter, bool* consume) { 2032 bool quit = false, dragging = false; 2033 while (!quit) { 2034 GdkEvent* eventPtr; 2035 while (true) { 2036 eventPtr = OS.gdk_event_get (); 2037 if (eventPtr !is null) { 2038 break; 2039 } else { 2040 try {Thread.sleep(50);} catch (Exception ex) {} 2041 } 2042 } 2043 switch (cast(int)OS.GDK_EVENT_TYPE (eventPtr)) { 2044 case OS.GDK_MOTION_NOTIFY: { 2045 GdkEventMotion* gdkMotionEvent = cast(GdkEventMotion*)eventPtr; 2046 if ((gdkMotionEvent.state & OS.GDK_BUTTON1_MASK) !is 0) { 2047 if (OS.gtk_drag_check_threshold (handle, x, y, cast(int) gdkMotionEvent.x, cast(int) gdkMotionEvent.y)) { 2048 dragging = true; 2049 quit = true; 2050 } 2051 } else { 2052 quit = true; 2053 } 2054 int newX, newY; 2055 OS.gdk_window_get_pointer (gdkMotionEvent.window, &newX, &newY, null); 2056 break; 2057 } 2058 case OS.GDK_KEY_PRESS: 2059 case OS.GDK_KEY_RELEASE: { 2060 GdkEventKey* gdkEvent = cast(GdkEventKey*)eventPtr; 2061 if (gdkEvent.keyval is OS.GDK_Escape) quit = true; 2062 break; 2063 } 2064 case OS.GDK_BUTTON_RELEASE: 2065 case OS.GDK_BUTTON_PRESS: 2066 case OS.GDK_2BUTTON_PRESS: 2067 case OS.GDK_3BUTTON_PRESS: { 2068 OS.gdk_event_put (eventPtr); 2069 quit = true; 2070 break; 2071 } 2072 default: 2073 OS.gtk_main_do_event (eventPtr); 2074 } 2075 OS.gdk_event_free (eventPtr); 2076 } 2077 return dragging; 2078 } 2079 2080 bool filterKey (int keyval, GdkEventKey* event) { 2081 auto imHandle = imHandle (); 2082 if (imHandle !is null) { 2083 return cast(bool)OS.gtk_im_context_filter_keypress (imHandle, event); 2084 } 2085 return false; 2086 } 2087 2088 Control findBackgroundControl () { 2089 if ((state & BACKGROUND) !is 0 || backgroundImage !is null) return this; 2090 return (state & PARENT_BACKGROUND) !is 0 ? parent.findBackgroundControl () : null; 2091 } 2092 2093 Menu [] findMenus (Control control) { 2094 if (menu !is null && this !is control) return [menu]; 2095 return new Menu [0]; 2096 } 2097 2098 void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) { 2099 oldShell.fixShell (newShell, this); 2100 oldDecorations.fixDecorations (newDecorations, this, menus); 2101 } 2102 2103 override int fixedMapProc (GtkWidget* widget) { 2104 OS.GTK_WIDGET_SET_FLAGS (widget, OS.GTK_MAPPED); 2105 auto widgetList = OS.gtk_container_get_children (cast(GtkContainer*)widget); 2106 if (widgetList !is null) { 2107 auto widgets = widgetList; 2108 while (widgets !is null) { 2109 auto child = cast(GtkWidget*)OS.g_list_data (widgets); 2110 if (OS.GTK_WIDGET_VISIBLE (child) && OS.gtk_widget_get_child_visible (child) && !OS.GTK_WIDGET_MAPPED (child)) { 2111 OS.gtk_widget_map (child); 2112 } 2113 widgets = cast(GList*)OS.g_list_next (widgets); 2114 } 2115 OS.g_list_free (widgetList); 2116 } 2117 if ((OS.GTK_WIDGET_FLAGS (widget) & OS.GTK_NO_WINDOW) is 0) { 2118 OS.gdk_window_show_unraised (OS.GTK_WIDGET_WINDOW (widget)); 2119 } 2120 return 0; 2121 } 2122 2123 void fixModal(GtkWidget* group, GtkWidget* modalGroup) { 2124 } 2125 2126 /** 2127 * Forces the receiver to have the <em>keyboard focus</em>, causing 2128 * all keyboard events to be delivered to it. 2129 * 2130 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to. 2131 * 2132 * @exception SWTException <ul> 2133 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2134 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2135 * </ul> 2136 * 2137 * @see #setFocus 2138 */ 2139 public bool forceFocus () { 2140 checkWidget(); 2141 if (display.focusEvent is SWT.FocusOut) return false; 2142 Shell shell = getShell (); 2143 shell.setSavedFocus (this); 2144 if (!isEnabled () || !isVisible ()) return false; 2145 shell.bringToTop (false); 2146 return forceFocus (focusHandle ()); 2147 } 2148 2149 bool forceFocus (GtkWidget* focusHandle_) { 2150 /* When the control is zero sized it must be realized */ 2151 OS.gtk_widget_realize (focusHandle_); 2152 OS.gtk_widget_grab_focus (focusHandle_); 2153 Shell shell = getShell (); 2154 auto shellHandle = shell.shellHandle; 2155 auto handle = OS.gtk_window_get_focus (cast(GtkWindow*)shellHandle); 2156 while (handle !is null) { 2157 if (handle is focusHandle_) return true; 2158 Widget widget = display.getWidget (handle); 2159 if (widget !is null && (null !is cast(Control)widget)) { 2160 return widget is this; 2161 } 2162 handle = OS.gtk_widget_get_parent (handle); 2163 } 2164 return false; 2165 } 2166 2167 /** 2168 * Returns the receiver's background color. 2169 * 2170 * @return the background color 2171 * 2172 * @exception SWTException <ul> 2173 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2174 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2175 * </ul> 2176 */ 2177 public Color getBackground () { 2178 checkWidget(); 2179 Control control = findBackgroundControl (); 2180 if (control is null) control = this; 2181 return Color.gtk_new (display, control.getBackgroundColor ()); 2182 } 2183 2184 GdkColor* getBackgroundColor () { 2185 return getBgColor (); 2186 } 2187 2188 /** 2189 * Returns the receiver's background image. 2190 * 2191 * @return the background image 2192 * 2193 * @exception SWTException <ul> 2194 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2195 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2196 * </ul> 2197 * 2198 * @since 3.2 2199 */ 2200 public Image getBackgroundImage () { 2201 checkWidget (); 2202 Control control = findBackgroundControl (); 2203 if (control is null) control = this; 2204 return control.backgroundImage; 2205 } 2206 2207 GdkColor* getBgColor () { 2208 auto fontHandle_ = fontHandle (); 2209 OS.gtk_widget_realize (fontHandle_); 2210 GdkColor* color = new GdkColor (); 2211 OS.gtk_style_get_bg (OS.gtk_widget_get_style (fontHandle_), OS.GTK_STATE_NORMAL, color); 2212 return color; 2213 } 2214 2215 GdkColor* getBaseColor () { 2216 auto fontHandle_ = fontHandle (); 2217 OS.gtk_widget_realize (fontHandle_); 2218 GdkColor* color = new GdkColor (); 2219 OS.gtk_style_get_base (OS.gtk_widget_get_style (fontHandle_), OS.GTK_STATE_NORMAL, color); 2220 return color; 2221 } 2222 2223 /** 2224 * Returns the receiver's border width. 2225 * 2226 * @return the border width 2227 * 2228 * @exception SWTException <ul> 2229 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2230 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2231 * </ul> 2232 */ 2233 public int getBorderWidth () { 2234 checkWidget(); 2235 return 0; 2236 } 2237 2238 int getClientWidth () { 2239 return 0; 2240 } 2241 2242 /** 2243 * Returns the receiver's cursor, or null if it has not been set. 2244 * <p> 2245 * When the mouse pointer passes over a control its appearance 2246 * is changed to match the control's cursor. 2247 * </p> 2248 * 2249 * @return the receiver's cursor or <code>null</code> 2250 * 2251 * @exception SWTException <ul> 2252 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2253 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2254 * </ul> 2255 * 2256 * @since 3.3 2257 */ 2258 public Cursor getCursor () { 2259 checkWidget (); 2260 return cursor; 2261 } 2262 2263 /** 2264 * Returns <code>true</code> if the receiver is detecting 2265 * drag gestures, and <code>false</code> otherwise. 2266 * 2267 * @return the receiver's drag detect state 2268 * 2269 * @exception SWTException <ul> 2270 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2271 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2272 * </ul> 2273 * 2274 * @since 3.3 2275 */ 2276 public bool getDragDetect () { 2277 checkWidget (); 2278 return (state & DRAG_DETECT) !is 0; 2279 } 2280 2281 /** 2282 * Returns <code>true</code> if the receiver is enabled, and 2283 * <code>false</code> otherwise. A disabled control is typically 2284 * not selectable from the user interface and draws with an 2285 * inactive or "grayed" look. 2286 * 2287 * @return the receiver's enabled state 2288 * 2289 * @exception SWTException <ul> 2290 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2291 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2292 * </ul> 2293 * 2294 * @see #isEnabled 2295 */ 2296 public bool getEnabled () { 2297 checkWidget (); 2298 return (state & DISABLED) is 0; 2299 } 2300 2301 /** 2302 * Returns the font that the receiver will use to paint textual information. 2303 * 2304 * @return the receiver's font 2305 * 2306 * @exception SWTException <ul> 2307 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2308 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2309 * </ul> 2310 */ 2311 public Font getFont () { 2312 checkWidget(); 2313 return font !is null ? font : defaultFont (); 2314 } 2315 2316 PangoFontDescription* getFontDescription () { 2317 auto fontHandle_ = fontHandle (); 2318 OS.gtk_widget_realize (fontHandle_); 2319 return OS.gtk_style_get_font_desc (OS.gtk_widget_get_style (fontHandle_)); 2320 } 2321 2322 /** 2323 * Returns the foreground color that the receiver will use to draw. 2324 * 2325 * @return the receiver's foreground color 2326 * 2327 * @exception SWTException <ul> 2328 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2329 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2330 * </ul> 2331 */ 2332 public Color getForeground () { 2333 checkWidget(); 2334 return Color.gtk_new (display, getForegroundColor ()); 2335 } 2336 2337 GdkColor* getForegroundColor () { 2338 return getFgColor (); 2339 } 2340 2341 GdkColor* getFgColor () { 2342 auto fontHandle_ = fontHandle (); 2343 OS.gtk_widget_realize (fontHandle_); 2344 GdkColor* color = new GdkColor (); 2345 OS.gtk_style_get_fg (OS.gtk_widget_get_style (fontHandle_), OS.GTK_STATE_NORMAL, color); 2346 return color; 2347 } 2348 2349 Point getIMCaretPos () { 2350 return new Point (0, 0); 2351 } 2352 2353 GdkColor* getTextColor () { 2354 auto fontHandle_ = fontHandle (); 2355 OS.gtk_widget_realize (fontHandle_); 2356 GdkColor* color = new GdkColor (); 2357 OS.gtk_style_get_text (OS.gtk_widget_get_style (fontHandle_), OS.GTK_STATE_NORMAL, color); 2358 return color; 2359 } 2360 2361 /** 2362 * Returns layout data which is associated with the receiver. 2363 * 2364 * @return the receiver's layout data 2365 * 2366 * @exception SWTException <ul> 2367 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2368 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2369 * </ul> 2370 */ 2371 public Object getLayoutData () { 2372 checkWidget(); 2373 return layoutData; 2374 } 2375 2376 /** 2377 * Returns the receiver's pop up menu if it has one, or null 2378 * if it does not. All controls may optionally have a pop up 2379 * menu that is displayed when the user requests one for 2380 * the control. The sequence of key strokes, button presses 2381 * and/or button releases that are used to request a pop up 2382 * menu is platform specific. 2383 * 2384 * @return the receiver's menu 2385 * 2386 * @exception SWTException <ul> 2387 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2388 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2389 * </ul> 2390 */ 2391 public Menu getMenu () { 2392 checkWidget(); 2393 return menu; 2394 } 2395 2396 /** 2397 * Returns the receiver's monitor. 2398 * 2399 * @return the receiver's monitor 2400 * 2401 * @since 3.0 2402 */ 2403 public org.eclipse.swt.widgets.Monitor.Monitor getMonitor () { 2404 checkWidget(); 2405 org.eclipse.swt.widgets.Monitor.Monitor monitor = null; 2406 auto screen = OS.gdk_screen_get_default (); 2407 if (screen !is null) { 2408 int monitorNumber = OS.gdk_screen_get_monitor_at_window (screen, paintWindow ()); 2409 GdkRectangle dest; 2410 OS.gdk_screen_get_monitor_geometry (screen, monitorNumber, &dest); 2411 monitor = new org.eclipse.swt.widgets.Monitor.Monitor (); 2412 monitor.handle = monitorNumber; 2413 monitor.x = dest.x; 2414 monitor.y = dest.y; 2415 monitor.width = dest.width; 2416 monitor.height = dest.height; 2417 Rectangle workArea = null; 2418 if (monitorNumber is 0) workArea = display.getWorkArea (); 2419 if (workArea !is null) { 2420 monitor.clientX = workArea.x; 2421 monitor.clientY = workArea.y; 2422 monitor.clientWidth = workArea.width; 2423 monitor.clientHeight = workArea.height; 2424 } else { 2425 monitor.clientX = monitor.x; 2426 monitor.clientY = monitor.y; 2427 monitor.clientWidth = monitor.width; 2428 monitor.clientHeight = monitor.height; 2429 } 2430 } else { 2431 monitor = display.getPrimaryMonitor (); 2432 } 2433 return monitor; 2434 } 2435 2436 /** 2437 * Returns the receiver's parent, which must be a <code>Composite</code> 2438 * or null when the receiver is a shell that was created with null or 2439 * a display for a parent. 2440 * 2441 * @return the receiver's parent 2442 * 2443 * @exception SWTException <ul> 2444 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2445 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2446 * </ul> 2447 */ 2448 public Composite getParent () { 2449 checkWidget(); 2450 return parent; 2451 } 2452 2453 Control [] getPath () { 2454 int count = 0; 2455 Shell shell = getShell (); 2456 Control control = this; 2457 while (control !is shell) { 2458 count++; 2459 control = control.parent; 2460 } 2461 control = this; 2462 Control [] result = new Control [count]; 2463 while (control !is shell) { 2464 result [--count] = control; 2465 control = control.parent; 2466 } 2467 return result; 2468 } 2469 2470 /** 2471 * Returns the region that defines the shape of the control, 2472 * or null if the control has the default shape. 2473 * 2474 * @return the region that defines the shape of the shell (or null) 2475 * 2476 * @exception SWTException <ul> 2477 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2478 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2479 * </ul> 2480 * 2481 * @since 3.4 2482 */ 2483 public Region getRegion () { 2484 checkWidget (); 2485 return region; 2486 } 2487 2488 /** 2489 * Returns the receiver's shell. For all controls other than 2490 * shells, this simply returns the control's nearest ancestor 2491 * shell. Shells return themselves, even if they are children 2492 * of other shells. 2493 * 2494 * @return the receiver's shell 2495 * 2496 * @exception SWTException <ul> 2497 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2498 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2499 * </ul> 2500 * 2501 * @see #getParent 2502 */ 2503 public Shell getShell() { 2504 checkWidget(); 2505 return _getShell(); 2506 } 2507 2508 Shell _getShell() { 2509 return parent._getShell(); 2510 } 2511 2512 /** 2513 * Returns the receiver's tool tip text, or null if it has 2514 * not been set. 2515 * 2516 * @return the receiver's tool tip text 2517 * 2518 * @exception SWTException <ul> 2519 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2520 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2521 * </ul> 2522 */ 2523 public String getToolTipText () { 2524 checkWidget(); 2525 return toolTipText; 2526 } 2527 /** 2528 * Returns <code>true</code> if the receiver is visible, and 2529 * <code>false</code> otherwise. 2530 * <p> 2531 * If one of the receiver's ancestors is not visible or some 2532 * other condition makes the receiver not visible, this method 2533 * may still indicate that it is considered visible even though 2534 * it may not actually be showing. 2535 * </p> 2536 * 2537 * @return the receiver's visibility state 2538 * 2539 * @exception SWTException <ul> 2540 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 2541 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 2542 * </ul> 2543 */ 2544 public bool getVisible () { 2545 checkWidget(); 2546 return (state & HIDDEN) is 0; 2547 } 2548 2549 override int gtk_button_press_event (GtkWidget* widget, GdkEventButton* event) { 2550 return gtk_button_press_event (widget, event, true); 2551 } 2552 2553 int gtk_button_press_event (GtkWidget* widget, GdkEventButton* gdkEvent, bool sendMouseDown) { 2554 if (gdkEvent.type is OS.GDK_3BUTTON_PRESS) return 0; 2555 2556 /* 2557 * When a shell is created with SWT.ON_TOP and SWT.NO_FOCUS, 2558 * do not activate the shell when the user clicks on the 2559 * the client area or on the border or a control within the 2560 * shell that does not take focus. 2561 */ 2562 Shell shell = _getShell (); 2563 if (((shell.style & SWT.ON_TOP) !is 0) && (((shell.style & SWT.NO_FOCUS) is 0) || ((style & SWT.NO_FOCUS) is 0))) { 2564 shell.forceActive(); 2565 } 2566 int result = 0; 2567 if (gdkEvent.type is OS.GDK_BUTTON_PRESS) { 2568 display.clickCount = 1; 2569 auto nextEvent = OS.gdk_event_peek (); 2570 if (nextEvent !is null) { 2571 int eventType = OS.GDK_EVENT_TYPE (nextEvent); 2572 if (eventType is OS.GDK_2BUTTON_PRESS) display.clickCount = 2; 2573 if (eventType is OS.GDK_3BUTTON_PRESS) display.clickCount = 3; 2574 OS.gdk_event_free (nextEvent); 2575 } 2576 bool dragging = false; 2577 if ((state & DRAG_DETECT) !is 0 && hooks (SWT.DragDetect)) { 2578 if (gdkEvent.button is 1) { 2579 bool consume = false; 2580 if (dragDetect (cast(int) gdkEvent.x, cast(int) gdkEvent.y, true, &consume)) { 2581 dragging = true; 2582 if (consume ) result = 1; 2583 } 2584 if (isDisposed ()) return 1; 2585 } 2586 } 2587 if (sendMouseDown && !sendMouseEvent (SWT.MouseDown, gdkEvent.button, display.clickCount, 0, false, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state)) { 2588 result = 1; 2589 } 2590 if (isDisposed ()) return 1; 2591 if (dragging) { 2592 sendDragEvent (gdkEvent.button, gdkEvent.state, cast(int)gdkEvent.x, cast(int)gdkEvent.y, false); 2593 if (isDisposed ()) return 1; 2594 } 2595 /* 2596 * Pop up the context menu in the button press event for widgets 2597 * that have default operating system menus in order to stop the 2598 * operating system from displaying the menu if necessary. 2599 */ 2600 if ((state & MENU) !is 0) { 2601 if (gdkEvent.button is 3) { 2602 if (showMenu (cast(int)gdkEvent.x_root, cast(int)gdkEvent.y_root)) { 2603 result = 1; 2604 } 2605 } 2606 } 2607 } else { 2608 display.clickCount = 2; 2609 result = sendMouseEvent (SWT.MouseDoubleClick, gdkEvent.button, display.clickCount, 0, false, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state) ? 0 : 1; 2610 if (isDisposed ()) return 1; 2611 } 2612 if (!shell.isDisposed ()) shell.setActiveControl (this); 2613 return result; 2614 } 2615 2616 override int gtk_button_release_event (GtkWidget* widget, GdkEventButton* gdkEvent) { 2617 /* 2618 * Feature in GTK. When button 4, 5, 6, or 7 is released, GTK 2619 * does not deliver a corresponding GTK event. Button 6 and 7 2620 * are mapped to buttons 4 and 5 in SWT. The fix is to change 2621 * the button number of the event to a negative number so that 2622 * it gets dispatched by GTK. SWT has been modified to look 2623 * for negative button numbers. 2624 */ 2625 int button = gdkEvent.button; 2626 switch (button) { 2627 case -6: button = 4; break; 2628 case -7: button = 5; break; 2629 default: 2630 } 2631 return sendMouseEvent (SWT.MouseUp, button, display.clickCount, 0, false, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state) ? 0 : 1; 2632 } 2633 2634 override int gtk_commit (GtkIMContext* imcontext, char* text) { 2635 char [] chars = fromStringz( text ); 2636 if (chars.length is 0) return 0; 2637 sendIMKeyEvent (SWT.KeyDown, null, chars); 2638 return 0; 2639 } 2640 2641 override int gtk_enter_notify_event (GtkWidget* widget, GdkEventCrossing* gdkEvent) { 2642 if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) { 2643 /* 2644 * Feature in GTK. Children of a shell will inherit and display the shell's 2645 * tooltip if they do not have a tooltip of their own. The fix is to use the 2646 * new tooltip API in GTK 2.12 to null the shell's tooltip when the control 2647 * being entered does not have any tooltip text set. 2648 */ 2649 char* buffer = null; 2650 if (toolTipText !is null && toolTipText.length !is 0) { 2651 char [] chars = fixMnemonic (toolTipText, false); 2652 buffer = toStringz(chars); 2653 } 2654 auto toolHandle = getShell().handle; 2655 OS.gtk_widget_set_tooltip_text (toolHandle, buffer); 2656 } 2657 if (display.currentControl is this) return 0; 2658 if (gdkEvent.mode !is OS.GDK_CROSSING_NORMAL && gdkEvent.mode !is OS.GDK_CROSSING_UNGRAB) return 0; 2659 if ((gdkEvent.state & (OS.GDK_BUTTON1_MASK | OS.GDK_BUTTON2_MASK | OS.GDK_BUTTON3_MASK)) !is 0) return 0; 2660 if (display.currentControl !is null && !display.currentControl.isDisposed ()) { 2661 display.removeMouseHoverTimeout (display.currentControl.handle); 2662 display.currentControl.sendMouseEvent (SWT.MouseExit, 0, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state); 2663 } 2664 if (!isDisposed ()) { 2665 display.currentControl = this; 2666 return sendMouseEvent (SWT.MouseEnter, 0, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state) ? 0 : 1; 2667 } 2668 return 0; 2669 } 2670 2671 override int gtk_event_after (GtkWidget* widget, GdkEvent* gdkEvent) { 2672 GdkEventButton* gdkEventButton = null; 2673 GdkEventFocus* gdkEventFocus = null; 2674 Display display = null; 2675 switch (cast(int)gdkEvent.type) { 2676 case OS.GDK_BUTTON_PRESS: { 2677 if (widget !is eventHandle ()) break; 2678 /* 2679 * Pop up the context menu in the event_after signal to allow 2680 * the widget to process the button press. This allows widgets 2681 * such as GtkTreeView to select items before a menu is shown. 2682 */ 2683 if ((state & MENU) is 0) { 2684 gdkEventButton = cast(GdkEventButton*)gdkEvent; 2685 if (gdkEventButton.button is 3) { 2686 showMenu (cast(int) gdkEventButton.x_root, cast(int) gdkEventButton.y_root); 2687 } 2688 } 2689 break; 2690 } 2691 case OS.GDK_FOCUS_CHANGE: { 2692 if (!isFocusHandle (widget)) break; 2693 gdkEventFocus = cast(GdkEventFocus*)gdkEvent; 2694 2695 /* 2696 * Feature in GTK. The GTK combo box popup under some window managers 2697 * is implemented as a GTK_MENU. When it pops up, it causes the combo 2698 * box to lose focus when focus is received for the menu. The 2699 * fix is to check the current grab handle and see if it is a GTK_MENU 2700 * and ignore the focus event when the menu is both shown and hidden. 2701 */ 2702 display = this.display; 2703 if (gdkEventFocus.in_ !is 0) { 2704 if (display.ignoreFocus) { 2705 display.ignoreFocus = false; 2706 break; 2707 } 2708 } else { 2709 display.ignoreFocus = false; 2710 auto grabHandle = OS.gtk_grab_get_current (); 2711 if (grabHandle !is null) { 2712 if (OS.G_OBJECT_TYPE ( cast(GTypeInstance*)grabHandle) is OS.GTK_TYPE_MENU ()) { 2713 display.ignoreFocus = true; 2714 break; 2715 } 2716 } 2717 } 2718 2719 sendFocusEvent (gdkEventFocus.in_ !is 0 ? SWT.FocusIn : SWT.FocusOut); 2720 break; 2721 default: 2722 } 2723 } 2724 return 0; 2725 } 2726 2727 override int gtk_expose_event (GtkWidget* widget, GdkEventExpose* gdkEvent) { 2728 if ((state & OBSCURED) !is 0) return 0; 2729 if (!hooks (SWT.Paint) && !filters (SWT.Paint)) return 0; 2730 Event event = new Event (); 2731 event.count = gdkEvent.count; 2732 event.x = gdkEvent.area.x; 2733 event.y = gdkEvent.area.y; 2734 event.width = gdkEvent.area.width; 2735 event.height = gdkEvent.area.height; 2736 if ((style & SWT.MIRRORED) !is 0) event.x = getClientWidth () - event.width - event.x; 2737 GCData data = new GCData (); 2738 data.damageRgn = gdkEvent.region; 2739 GC gc = event.gc = GC.gtk_new (this, data); 2740 OS.gdk_gc_set_clip_region (gc.handle, gdkEvent.region); 2741 sendEvent (SWT.Paint, event); 2742 gc.dispose (); 2743 event.gc = null; 2744 return 0; 2745 } 2746 2747 override int gtk_focus (GtkWidget* widget, ptrdiff_t directionType) { 2748 /* Stop GTK traversal for every widget */ 2749 return 1; 2750 } 2751 2752 override int gtk_focus_in_event (GtkWidget* widget, GdkEventFocus* event) { 2753 // widget could be disposed at this point 2754 if (handle !is null) { 2755 Control oldControl = display.imControl; 2756 if (oldControl !is this) { 2757 if (oldControl !is null && !oldControl.isDisposed ()) { 2758 auto oldIMHandle = oldControl.imHandle (); 2759 if (oldIMHandle !is null) OS.gtk_im_context_reset (oldIMHandle); 2760 } 2761 } 2762 if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) { 2763 auto imHandle = imHandle (); 2764 if (imHandle !is null) OS.gtk_im_context_focus_in (imHandle); 2765 } 2766 } 2767 return 0; 2768 } 2769 2770 override int gtk_focus_out_event (GtkWidget* widget, GdkEventFocus* event) { 2771 // widget could be disposed at this point 2772 if (handle !is null) { 2773 if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) { 2774 auto imHandle = imHandle (); 2775 if (imHandle !is null) { 2776 OS.gtk_im_context_focus_out (imHandle); 2777 } 2778 } 2779 } 2780 return 0; 2781 } 2782 2783 override int gtk_key_press_event (GtkWidget* widget, GdkEventKey* gdkEvent) { 2784 if (!hasFocus ()) return 0; 2785 2786 if (translateMnemonic (gdkEvent.keyval, gdkEvent)) return 1; 2787 // widget could be disposed at this point 2788 if (isDisposed ()) return 0; 2789 2790 if (filterKey (gdkEvent.keyval, gdkEvent)) return 1; 2791 // widget could be disposed at this point 2792 if (isDisposed ()) return 0; 2793 2794 if (translateTraversal (gdkEvent)) return 1; 2795 // widget could be disposed at this point 2796 if (isDisposed ()) return 0; 2797 return super.gtk_key_press_event (widget, gdkEvent); 2798 } 2799 2800 override int gtk_key_release_event (GtkWidget* widget, GdkEventKey* event) { 2801 if (!hasFocus ()) return 0; 2802 auto imHandle = imHandle (); 2803 if (imHandle !is null) { 2804 if (OS.gtk_im_context_filter_keypress (imHandle, event)) return 1; 2805 } 2806 return super.gtk_key_release_event (widget, event); 2807 } 2808 2809 override int gtk_leave_notify_event (GtkWidget* widget, GdkEventCrossing* gdkEvent) { 2810 if (display.currentControl !is this) return 0; 2811 display.removeMouseHoverTimeout (handle); 2812 int result = 0; 2813 if (sendLeaveNotify () || display.getCursorControl () is null) { 2814 if (gdkEvent.mode !is OS.GDK_CROSSING_NORMAL && gdkEvent.mode !is OS.GDK_CROSSING_UNGRAB) return 0; 2815 if ((gdkEvent.state & (OS.GDK_BUTTON1_MASK | OS.GDK_BUTTON2_MASK | OS.GDK_BUTTON3_MASK)) !is 0) return 0; 2816 result = sendMouseEvent (SWT.MouseExit, 0, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state) ? 0 : 1; 2817 display.currentControl = null; 2818 } 2819 return result; 2820 } 2821 2822 override int gtk_mnemonic_activate (GtkWidget* widget, ptrdiff_t arg1) { 2823 int result = 0; 2824 auto eventPtr = OS.gtk_get_current_event (); 2825 if (eventPtr !is null) { 2826 GdkEventKey* keyEvent = cast(GdkEventKey*)eventPtr; 2827 if (keyEvent.type is OS.GDK_KEY_PRESS) { 2828 Control focusControl = display.getFocusControl (); 2829 auto focusHandle_ = focusControl !is null ? focusControl.focusHandle () : null; 2830 if (focusHandle_ !is null) { 2831 display.mnemonicControl = this; 2832 OS.gtk_widget_event (focusHandle_, eventPtr); 2833 display.mnemonicControl = null; 2834 } 2835 result = 1; 2836 } 2837 OS.gdk_event_free (eventPtr); 2838 } 2839 return result; 2840 } 2841 2842 override int gtk_motion_notify_event (GtkWidget* widget, GdkEventMotion* gdkEvent) { 2843 if (this is display.currentControl && (hooks (SWT.MouseHover) || filters (SWT.MouseHover))) { 2844 display.addMouseHoverTimeout (handle); 2845 } 2846 double x = gdkEvent.x_root, y = gdkEvent.y_root; 2847 int state = gdkEvent.state; 2848 if (gdkEvent.is_hint !is 0) { 2849 int pointer_x, pointer_y; 2850 int mask; 2851 auto window = eventWindow (); 2852 OS.gdk_window_get_pointer (window, &pointer_x, &pointer_y, &mask); 2853 x = pointer_x; 2854 y = pointer_y; 2855 state = mask; 2856 } 2857 int result = sendMouseEvent (SWT.MouseMove, 0, gdkEvent.time, x, y, gdkEvent.is_hint !is 0, state) ? 0 : 1; 2858 return result; 2859 } 2860 2861 override int gtk_popup_menu (GtkWidget* widget) { 2862 if (!hasFocus()) return 0; 2863 int x, y ; 2864 OS.gdk_window_get_pointer (null, &x, &y, null); 2865 return showMenu (x, y) ? 1 : 0; 2866 } 2867 2868 override int gtk_preedit_changed (GtkIMContext* imcontext) { 2869 display.showIMWindow (this); 2870 return 0; 2871 } 2872 2873 override int gtk_realize (GtkWidget* widget) { 2874 auto imHandle = imHandle (); 2875 if (imHandle !is null) { 2876 auto window = OS.GTK_WIDGET_WINDOW (paintHandle ()); 2877 OS.gtk_im_context_set_client_window (imHandle, window); 2878 } 2879 if (backgroundImage !is null) { 2880 auto window = OS.GTK_WIDGET_WINDOW (paintHandle ()); 2881 if (window !is null) OS.gdk_window_set_back_pixmap (window, cast(GdkPixmap*)backgroundImage.pixmap, false); 2882 } 2883 return 0; 2884 } 2885 2886 override int gtk_scroll_event (GtkWidget* widget, GdkEventScroll* gdkEvent) { 2887 switch (gdkEvent.direction) { 2888 case OS.GDK_SCROLL_UP: 2889 return sendMouseEvent (SWT.MouseWheel, 0, 3, SWT.SCROLL_LINE, true, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state) ? 0 : 1; 2890 case OS.GDK_SCROLL_DOWN: 2891 return sendMouseEvent (SWT.MouseWheel, 0, -3, SWT.SCROLL_LINE, true, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state) ? 0 : 1; 2892 case OS.GDK_SCROLL_LEFT: 2893 return sendMouseEvent (SWT.MouseDown, 4, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state) ? 0 : 1; 2894 case OS.GDK_SCROLL_RIGHT: 2895 return sendMouseEvent (SWT.MouseDown, 5, gdkEvent.time, gdkEvent.x_root, gdkEvent.y_root, false, gdkEvent.state) ? 0 : 1; 2896 default: 2897 } 2898 return 0; 2899 } 2900 2901 override int gtk_show_help (GtkWidget* widget, ptrdiff_t helpType) { 2902 if (!hasFocus ()) return 0; 2903 return sendHelpEvent (helpType) ? 1 : 0; 2904 } 2905 2906 override int gtk_style_set (GtkWidget* widget, ptrdiff_t previousStyle) { 2907 if (backgroundImage !is null) { 2908 setBackgroundPixmap (backgroundImage.pixmap); 2909 } 2910 return 0; 2911 } 2912 2913 override int gtk_unrealize (GtkWidget* widget) { 2914 auto imHandle = imHandle (); 2915 if (imHandle !is null) OS.gtk_im_context_set_client_window (imHandle, null); 2916 return 0; 2917 } 2918 2919 override int gtk_visibility_notify_event (GtkWidget* widget, GdkEventVisibility* gdkEvent) { 2920 auto paintWindow = paintWindow(); 2921 auto window = gdkEvent.window; 2922 if (window is paintWindow) { 2923 if (gdkEvent.state is OS.GDK_VISIBILITY_FULLY_OBSCURED) { 2924 state |= OBSCURED; 2925 } else { 2926 if ((state & OBSCURED) !is 0) { 2927 int width, height; 2928 OS.gdk_drawable_get_size (cast(GdkDrawable*)window, &width, &height); 2929 GdkRectangle rect; 2930 rect.width = width; 2931 rect.height = height; 2932 OS.gdk_window_invalidate_rect (window, &rect, false); 2933 } 2934 state &= ~OBSCURED; 2935 } 2936 } 2937 return 0; 2938 } 2939 2940 /*no override*/ void gtk_widget_size_request (GtkWidget* widget, GtkRequisition* requisition) { 2941 OS.gtk_widget_size_request (widget, requisition); 2942 } 2943 2944 /** 2945 * Invokes platform specific functionality to allocate a new GC handle. 2946 * <p> 2947 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public 2948 * API for <code>Control</code>. It is marked public only so that it 2949 * can be shared within the packages provided by SWT. It is not 2950 * available on all platforms, and should never be called from 2951 * application code. 2952 * </p> 2953 * 2954 * @param data the platform specific GC data 2955 * @return the platform specific GC handle 2956 */ 2957 public GdkGC* internal_new_GC (GCData data) { 2958 checkWidget (); 2959 auto window = paintWindow (); 2960 if (window is null) SWT.error (SWT.ERROR_NO_HANDLES); 2961 auto gdkGC = OS.gdk_gc_new (cast(GdkDrawable*)window); 2962 if (gdkGC is null) error (SWT.ERROR_NO_HANDLES); 2963 if (data !is null) { 2964 int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; 2965 if ((data.style & mask) is 0) { 2966 data.style |= style & (mask | SWT.MIRRORED); 2967 } else { 2968 if ((data.style & SWT.RIGHT_TO_LEFT) !is 0) { 2969 data.style |= SWT.MIRRORED; 2970 } 2971 } 2972 data.drawable = cast(GdkDrawable*)window; 2973 data.device = display; 2974 data.foreground = getForegroundColor (); 2975 Control control = findBackgroundControl (); 2976 if (control is null) control = this; 2977 data.background = control.getBackgroundColor (); 2978 data.font = font !is null ? font : defaultFont (); 2979 } 2980 return gdkGC; 2981 } 2982 2983 GtkIMContext* imHandle () { 2984 return null; 2985 } 2986 2987 /** 2988 * Invokes platform specific functionality to dispose a GC handle. 2989 * <p> 2990 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public 2991 * API for <code>Control</code>. It is marked public only so that it 2992 * can be shared within the packages provided by SWT. It is not 2993 * available on all platforms, and should never be called from 2994 * application code. 2995 * </p> 2996 * 2997 * @param hDC the platform specific GC handle 2998 * @param data the platform specific GC data 2999 */ 3000 public void internal_dispose_GC (GdkGC* gdkGC, GCData data) { 3001 checkWidget (); 3002 OS.g_object_unref (gdkGC); 3003 } 3004 3005 /** 3006 * Returns <code>true</code> if the underlying operating 3007 * system supports this reparenting, otherwise <code>false</code> 3008 * 3009 * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code> 3010 * 3011 * @exception SWTException <ul> 3012 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3013 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3014 * </ul> 3015 */ 3016 public bool isReparentable () { 3017 checkWidget(); 3018 return true; 3019 } 3020 bool isShowing () { 3021 /* 3022 * This is not complete. Need to check if the 3023 * widget is obscurred by a parent or sibling. 3024 */ 3025 if (!isVisible ()) return false; 3026 Control control = this; 3027 while (control !is null) { 3028 Point size = control.getSize (); 3029 if (size.x is 0 || size.y is 0) { 3030 return false; 3031 } 3032 control = control.parent; 3033 } 3034 return true; 3035 } 3036 bool isTabGroup () { 3037 Control [] tabList = parent._getTabList (); 3038 if (tabList !is null) { 3039 for (int i=0; i<tabList.length; i++) { 3040 if (tabList [i] is this) return true; 3041 } 3042 } 3043 int code = traversalCode (0, null); 3044 if ((code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) !is 0) return false; 3045 return (code & (SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_TAB_NEXT)) !is 0; 3046 } 3047 bool isTabItem () { 3048 Control [] tabList = parent._getTabList (); 3049 if (tabList !is null) { 3050 for (int i=0; i<tabList.length; i++) { 3051 if (tabList [i] is this) return false; 3052 } 3053 } 3054 int code = traversalCode (0, null); 3055 return (code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) !is 0; 3056 } 3057 3058 /** 3059 * Returns <code>true</code> if the receiver is enabled and all 3060 * ancestors up to and including the receiver's nearest ancestor 3061 * shell are enabled. Otherwise, <code>false</code> is returned. 3062 * A disabled control is typically not selectable from the user 3063 * interface and draws with an inactive or "grayed" look. 3064 * 3065 * @return the receiver's enabled state 3066 * 3067 * @exception SWTException <ul> 3068 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3069 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3070 * </ul> 3071 * 3072 * @see #getEnabled 3073 */ 3074 public bool isEnabled () { 3075 checkWidget (); 3076 return getEnabled () && parent.isEnabled (); 3077 } 3078 3079 bool isFocusAncestor (Control control) { 3080 while (control !is null && control !is this && !( null !is cast(Shell)control )) { 3081 control = control.parent; 3082 } 3083 return control is this; 3084 } 3085 3086 /** 3087 * Returns <code>true</code> if the receiver has the user-interface 3088 * focus, and <code>false</code> otherwise. 3089 * 3090 * @return the receiver's focus state 3091 * 3092 * @exception SWTException <ul> 3093 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3094 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3095 * </ul> 3096 */ 3097 public bool isFocusControl () { 3098 checkWidget(); 3099 Control focusControl = display.focusControl; 3100 if (focusControl !is null && !focusControl.isDisposed ()) { 3101 return this is focusControl; 3102 } 3103 return hasFocus (); 3104 } 3105 3106 /** 3107 * Returns <code>true</code> if the receiver is visible and all 3108 * ancestors up to and including the receiver's nearest ancestor 3109 * shell are visible. Otherwise, <code>false</code> is returned. 3110 * 3111 * @return the receiver's visibility state 3112 * 3113 * @exception SWTException <ul> 3114 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3115 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3116 * </ul> 3117 * 3118 * @see #getVisible 3119 */ 3120 public bool isVisible () { 3121 checkWidget(); 3122 return getVisible () && parent.isVisible (); 3123 } 3124 3125 Decorations menuShell () { 3126 return parent.menuShell (); 3127 } 3128 3129 bool mnemonicHit (wchar key) { 3130 return false; 3131 } 3132 3133 bool mnemonicMatch (wchar key) { 3134 return false; 3135 } 3136 3137 override void register () { 3138 super.register (); 3139 if (fixedHandle !is null) display.addWidget (fixedHandle, this); 3140 auto imHandle = imHandle (); 3141 if (imHandle !is null) display.addWidget (cast(GtkWidget*)imHandle, this); 3142 } 3143 3144 /** 3145 * Causes the entire bounds of the receiver to be marked 3146 * as needing to be redrawn. The next time a paint request 3147 * is processed, the control will be completely painted, 3148 * including the background. 3149 * 3150 * @exception SWTException <ul> 3151 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3152 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3153 * </ul> 3154 * 3155 * @see #update() 3156 * @see PaintListener 3157 * @see SWT#Paint 3158 * @see SWT#NO_BACKGROUND 3159 * @see SWT#NO_REDRAW_RESIZE 3160 * @see SWT#NO_MERGE_PAINTS 3161 * @see SWT#DOUBLE_BUFFERED 3162 */ 3163 public void redraw () { 3164 checkWidget(); 3165 redraw (false); 3166 } 3167 3168 void redraw (bool all) { 3169 // checkWidget(); 3170 if (!OS.GTK_WIDGET_VISIBLE (topHandle ())) return; 3171 redrawWidget (0, 0, 0, 0, true, all, false); 3172 } 3173 3174 /** 3175 * Causes the rectangular area of the receiver specified by 3176 * the arguments to be marked as needing to be redrawn. 3177 * The next time a paint request is processed, that area of 3178 * the receiver will be painted, including the background. 3179 * If the <code>all</code> flag is <code>true</code>, any 3180 * children of the receiver which intersect with the specified 3181 * area will also paint their intersecting areas. If the 3182 * <code>all</code> flag is <code>false</code>, the children 3183 * will not be painted. 3184 * 3185 * @param x the x coordinate of the area to draw 3186 * @param y the y coordinate of the area to draw 3187 * @param width the width of the area to draw 3188 * @param height the height of the area to draw 3189 * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise 3190 * 3191 * @exception SWTException <ul> 3192 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3193 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3194 * </ul> 3195 * 3196 * @see #update() 3197 * @see PaintListener 3198 * @see SWT#Paint 3199 * @see SWT#NO_BACKGROUND 3200 * @see SWT#NO_REDRAW_RESIZE 3201 * @see SWT#NO_MERGE_PAINTS 3202 * @see SWT#DOUBLE_BUFFERED 3203 */ 3204 public void redraw (int x, int y, int width, int height, bool all) { 3205 checkWidget(); 3206 if (!OS.GTK_WIDGET_VISIBLE (topHandle ())) return; 3207 if ((style & SWT.MIRRORED) !is 0) x = getClientWidth () - width - x; 3208 redrawWidget (x, y, width, height, false, all, false); 3209 } 3210 3211 void redrawChildren () { 3212 } 3213 3214 void redrawWidget (int x, int y, int width, int height, bool redrawAll, bool all, bool trim) { 3215 if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) is 0) return; 3216 auto window = paintWindow (); 3217 GdkRectangle rect; 3218 if (redrawAll) { 3219 int w, h; 3220 OS.gdk_drawable_get_size (cast(GdkDrawable*)window, &w, &h); 3221 rect.width = w; 3222 rect.height = h; 3223 } else { 3224 rect.x = x; 3225 rect.y = y; 3226 rect.width = width; 3227 rect.height = height; 3228 } 3229 OS.gdk_window_invalidate_rect (window, &rect, all); 3230 } 3231 3232 override void release (bool destroy) { 3233 Control next = null, previous = null; 3234 if (destroy && parent !is null) { 3235 Control[] children = parent._getChildren (); 3236 int index = 0; 3237 while (index < children.length) { 3238 if (children [index] is this) break; 3239 index++; 3240 } 3241 if (0 < index && (index + 1) < children.length) { 3242 next = children [index + 1]; 3243 previous = children [index - 1]; 3244 } 3245 } 3246 super.release (destroy); 3247 if (destroy) { 3248 if (previous !is null) previous.addRelation (next); 3249 } 3250 } 3251 3252 override void releaseHandle () { 3253 super.releaseHandle (); 3254 fixedHandle = null; 3255 parent = null; 3256 } 3257 3258 override void releaseParent () { 3259 parent.removeControl (this); 3260 } 3261 3262 override void releaseWidget () { 3263 super.releaseWidget (); 3264 if (display.currentControl is this) display.currentControl = null; 3265 display.removeMouseHoverTimeout (handle); 3266 auto imHandle = imHandle (); 3267 if (imHandle !is null) { 3268 OS.gtk_im_context_reset (imHandle); 3269 OS.gtk_im_context_set_client_window (imHandle, null); 3270 } 3271 if (enableWindow !is null) { 3272 OS.gdk_window_set_user_data (enableWindow, null); 3273 OS.gdk_window_destroy (enableWindow); 3274 enableWindow = null; 3275 } 3276 redrawWindow = null; 3277 if (menu !is null && !menu.isDisposed ()) { 3278 menu.dispose (); 3279 } 3280 menu = null; 3281 cursor = null; 3282 toolTipText = null; 3283 layoutData = null; 3284 accessible = null; 3285 region = null; 3286 } 3287 3288 bool sendDragEvent (int button, int stateMask, int x, int y, bool isStateMask) { 3289 Event event = new Event (); 3290 event.button = button; 3291 event.x = x; 3292 event.y = y; 3293 if ((style & SWT.MIRRORED) !is 0) event.x = getClientWidth () - event.x; 3294 if (isStateMask) { 3295 event.stateMask = stateMask; 3296 } else { 3297 setInputState (event, stateMask); 3298 } 3299 postEvent (SWT.DragDetect, event); 3300 if (isDisposed ()) return false; 3301 return event.doit; 3302 } 3303 3304 void sendFocusEvent (int type) { 3305 Shell shell = _getShell (); 3306 Display display = this.display; 3307 display.focusControl = this; 3308 display.focusEvent = type; 3309 sendEvent (type); 3310 display.focusControl = null; 3311 display.focusEvent = SWT.None; 3312 /* 3313 * It is possible that the shell may be 3314 * disposed at this point. If this happens 3315 * don't send the activate and deactivate 3316 * events. 3317 */ 3318 if (!shell.isDisposed ()) { 3319 switch (type) { 3320 case SWT.FocusIn: 3321 shell.setActiveControl (this); 3322 break; 3323 case SWT.FocusOut: 3324 if (shell !is display.activeShell) { 3325 shell.setActiveControl (null); 3326 } 3327 break; 3328 default: 3329 } 3330 } 3331 } 3332 3333 bool sendHelpEvent (ptrdiff_t helpType) { 3334 Control control = this; 3335 while (control !is null) { 3336 if (control.hooks (SWT.Help)) { 3337 control.postEvent (SWT.Help); 3338 return true; 3339 } 3340 control = control.parent; 3341 } 3342 return false; 3343 } 3344 3345 bool sendLeaveNotify() { 3346 return false; 3347 } 3348 3349 bool sendMouseEvent (int type, int button, int time, double x, double y, bool is_hint, int state) { 3350 return sendMouseEvent (type, button, 0, 0, false, time, x, y, is_hint, state); 3351 } 3352 3353 bool sendMouseEvent (int type, int button, int count, int detail, bool send, int time, double x, double y, bool is_hint, int state) { 3354 if (!hooks (type) && !filters (type)) return true; 3355 Event event = new Event (); 3356 event.time = time; 3357 event.button = button; 3358 event.detail = detail; 3359 event.count = count; 3360 if (is_hint) { 3361 event.x = cast(int)x; 3362 event.y = cast(int)y; 3363 } else { 3364 auto window = eventWindow (); 3365 int origin_x, origin_y; 3366 OS.gdk_window_get_origin (window, &origin_x, &origin_y); 3367 event.x = cast(int)(x - origin_x); 3368 event.y = cast(int)(y - origin_y); 3369 } 3370 if ((style & SWT.MIRRORED) !is 0) event.x = getClientWidth () - event.x; 3371 setInputState (event, state); 3372 if (send) { 3373 sendEvent (type, event); 3374 if (isDisposed ()) return false; 3375 } else { 3376 postEvent (type, event); 3377 } 3378 return event.doit; 3379 } 3380 3381 void setBackground () { 3382 if ((state & PARENT_BACKGROUND) !is 0 && (state & BACKGROUND) is 0 && backgroundImage is null) { 3383 setParentBackground (); 3384 } else { 3385 setWidgetBackground (); 3386 } 3387 redrawWidget (0, 0, 0, 0, true, false, false); 3388 } 3389 3390 /** 3391 * Sets the receiver's background color to the color specified 3392 * by the argument, or to the default system color for the control 3393 * if the argument is null. 3394 * <p> 3395 * Note: This operation is a hint and may be overridden by the platform. 3396 * For example, on Windows the background of a Button cannot be changed. 3397 * </p> 3398 * @param color the new color (or null) 3399 * 3400 * @exception IllegalArgumentException <ul> 3401 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 3402 * </ul> 3403 * @exception SWTException <ul> 3404 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3405 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3406 * </ul> 3407 */ 3408 public void setBackground (Color color) { 3409 checkWidget(); 3410 if (((state & BACKGROUND) is 0) && color is null) return; 3411 GdkColor* gdkColor = null; 3412 if (color !is null) { 3413 if (color.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); 3414 gdkColor = color.handle; 3415 } 3416 bool set = false; 3417 if (gdkColor is null) { 3418 auto style = OS.gtk_widget_get_modifier_style (handle); 3419 set = (OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_NORMAL) & OS.GTK_RC_BG) !is 0; 3420 } else { 3421 GdkColor* oldColor = getBackgroundColor (); 3422 set = oldColor.pixel !is gdkColor.pixel; 3423 } 3424 if (set) { 3425 if (color is null) { 3426 state &= ~BACKGROUND; 3427 } else { 3428 state |= BACKGROUND; 3429 } 3430 setBackgroundColor (gdkColor); 3431 redrawChildren (); 3432 } 3433 } 3434 3435 void setBackgroundColor (GtkWidget* handle, GdkColor* color) { 3436 int index = OS.GTK_STATE_NORMAL; 3437 auto style = OS.gtk_widget_get_modifier_style (handle); 3438 auto ptr = OS.gtk_rc_style_get_bg_pixmap_name (style, index); 3439 if (ptr !is null) OS.g_free (ptr); 3440 String name = color is null ? "<parent>" : "<none>" ; 3441 ptr = cast(char*)OS.g_malloc (name.length+1); 3442 ptr[ 0 .. name.length ] = name; 3443 ptr[ name.length ] = '\0'; 3444 OS.gtk_rc_style_set_bg_pixmap_name (style, index, ptr); 3445 OS.gtk_rc_style_set_bg (style, index, color); 3446 int flags = OS.gtk_rc_style_get_color_flags (style, index); 3447 flags = (color is null) ? flags & ~OS.GTK_RC_BG : flags | OS.GTK_RC_BG; 3448 OS.gtk_rc_style_set_color_flags (style, index, flags); 3449 modifyStyle (handle, style); 3450 } 3451 3452 void setBackgroundColor (GdkColor* color) { 3453 setBackgroundColor (handle, color); 3454 } 3455 3456 /** 3457 * Sets the receiver's background image to the image specified 3458 * by the argument, or to the default system color for the control 3459 * if the argument is null. The background image is tiled to fill 3460 * the available space. 3461 * <p> 3462 * Note: This operation is a hint and may be overridden by the platform. 3463 * For example, on Windows the background of a Button cannot be changed. 3464 * </p> 3465 * @param image the new image (or null) 3466 * 3467 * @exception IllegalArgumentException <ul> 3468 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 3469 * <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</li> 3470 * </ul> 3471 * @exception SWTException <ul> 3472 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3473 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3474 * </ul> 3475 * 3476 * @since 3.2 3477 */ 3478 public void setBackgroundImage (Image image) { 3479 checkWidget (); 3480 if (image !is null && image.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); 3481 if (image is backgroundImage) return; 3482 this.backgroundImage = image; 3483 if (backgroundImage !is null) { 3484 setBackgroundPixmap (backgroundImage.pixmap); 3485 redrawWidget (0, 0, 0, 0, true, false, false); 3486 } else { 3487 setWidgetBackground (); 3488 } 3489 redrawChildren (); 3490 } 3491 3492 void setBackgroundPixmap (GdkDrawable* pixmap) { 3493 auto window = OS.GTK_WIDGET_WINDOW (paintHandle ()); 3494 if (window !is null) OS.gdk_window_set_back_pixmap (window, cast(GdkPixmap*)backgroundImage.pixmap, false); 3495 } 3496 3497 /** 3498 * If the argument is <code>true</code>, causes the receiver to have 3499 * all mouse events delivered to it until the method is called with 3500 * <code>false</code> as the argument. Note that on some platforms, 3501 * a mouse button must currently be down for capture to be assigned. 3502 * 3503 * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it 3504 * 3505 * @exception SWTException <ul> 3506 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3507 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3508 * </ul> 3509 */ 3510 public void setCapture (bool capture) { 3511 checkWidget(); 3512 /* FIXME !!!!! */ 3513 /* 3514 if (capture) { 3515 OS.gtk_widget_grab_focus (handle); 3516 } else { 3517 OS.gtk_widget_grab_default (handle); 3518 } 3519 */ 3520 } 3521 /** 3522 * Sets the receiver's cursor to the cursor specified by the 3523 * argument, or to the default cursor for that kind of control 3524 * if the argument is null. 3525 * <p> 3526 * When the mouse pointer passes over a control its appearance 3527 * is changed to match the control's cursor. 3528 * </p> 3529 * 3530 * @param cursor the new cursor (or null) 3531 * 3532 * @exception IllegalArgumentException <ul> 3533 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 3534 * </ul> 3535 * @exception SWTException <ul> 3536 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3537 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3538 * </ul> 3539 */ 3540 public void setCursor (Cursor cursor) { 3541 checkWidget(); 3542 if (cursor !is null && cursor.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); 3543 this.cursor = cursor; 3544 gtk_setCursor (cursor !is null ? cursor.handle : null); 3545 } 3546 3547 void gtk_setCursor (GdkCursor* cursor) { 3548 auto window = eventWindow (); 3549 if (window !is null) { 3550 OS.gdk_window_set_cursor (window, cursor); 3551 if (!OS.GDK_WINDOWING_X11 ()) { 3552 OS.gdk_flush (); 3553 } else { 3554 auto xDisplay = OS.GDK_DISPLAY (); 3555 OS.XFlush (xDisplay); 3556 } 3557 } 3558 } 3559 3560 /** 3561 * Sets the receiver's drag detect state. If the argument is 3562 * <code>true</code>, the receiver will detect drag gestures, 3563 * otherwise these gestures will be ignored. 3564 * 3565 * @param dragDetect the new drag detect state 3566 * 3567 * @exception SWTException <ul> 3568 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3569 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3570 * </ul> 3571 * 3572 * @since 3.3 3573 */ 3574 public void setDragDetect (bool dragDetect) { 3575 checkWidget (); 3576 if (dragDetect) { 3577 state |= DRAG_DETECT; 3578 } else { 3579 state &= ~DRAG_DETECT; 3580 } 3581 } 3582 3583 /** 3584 * Enables the receiver if the argument is <code>true</code>, 3585 * and disables it otherwise. A disabled control is typically 3586 * not selectable from the user interface and draws with an 3587 * inactive or "grayed" look. 3588 * 3589 * @param enabled the new enabled state 3590 * 3591 * @exception SWTException <ul> 3592 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3593 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3594 * </ul> 3595 */ 3596 public void setEnabled (bool enabled) { 3597 checkWidget(); 3598 if (((state & DISABLED) is 0) is enabled) return; 3599 Control control = null; 3600 bool fixFocus_ = false; 3601 if (!enabled) { 3602 if (display.focusEvent !is SWT.FocusOut) { 3603 control = display.getFocusControl (); 3604 fixFocus_ = isFocusAncestor (control); 3605 } 3606 } 3607 if (enabled) { 3608 state &= ~DISABLED; 3609 } else { 3610 state |= DISABLED; 3611 } 3612 enableWidget (enabled); 3613 if (isDisposed ()) return; 3614 if (enabled) { 3615 if (enableWindow !is null) { 3616 OS.gdk_window_set_user_data (enableWindow, null); 3617 OS.gdk_window_destroy (enableWindow); 3618 enableWindow = null; 3619 } 3620 } else { 3621 OS.gtk_widget_realize (handle); 3622 auto parentHandle = parent.eventHandle (); 3623 auto window = parent.eventWindow(); 3624 auto topHandle_ = topHandle (); 3625 GdkWindowAttr attributes; 3626 attributes.x = OS.GTK_WIDGET_X (topHandle_); 3627 attributes.y = OS.GTK_WIDGET_Y (topHandle_); 3628 attributes.width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); 3629 attributes.height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_); 3630 attributes.event_mask = (0xFFFFFFFF & ~OS.ExposureMask); 3631 attributes.wclass = OS.GDK_INPUT_ONLY; 3632 attributes.window_type = OS.GDK_WINDOW_CHILD; 3633 enableWindow = OS.gdk_window_new (window, &attributes, OS.GDK_WA_X | OS.GDK_WA_Y); 3634 if (enableWindow !is null) { 3635 OS.gdk_window_set_user_data (enableWindow, parentHandle); 3636 if (!OS.GDK_WINDOWING_X11 ()) { 3637 OS.gdk_window_raise (enableWindow); 3638 } else { 3639 auto topWindow = OS.GTK_WIDGET_WINDOW (topHandle_); 3640 auto xDisplay = OS.gdk_x11_drawable_get_xdisplay (cast(GdkDrawable*)topWindow); 3641 auto xWindow = OS.gdk_x11_drawable_get_xid (cast(GdkDrawable*)enableWindow); 3642 int xScreen = OS.XDefaultScreen (xDisplay); 3643 int flags = OS.CWStackMode | OS.CWSibling; 3644 XWindowChanges changes; 3645 changes.sibling = OS.gdk_x11_drawable_get_xid (cast(GdkDrawable*)topWindow); 3646 changes.stack_mode = OS.Above; 3647 OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, &changes); 3648 } 3649 if (OS.GTK_WIDGET_VISIBLE (topHandle_)) OS.gdk_window_show_unraised (enableWindow); 3650 } 3651 } 3652 if (fixFocus_) fixFocus (control); 3653 } 3654 3655 /** 3656 * Causes the receiver to have the <em>keyboard focus</em>, 3657 * such that all keyboard events will be delivered to it. Focus 3658 * reassignment will respect applicable platform constraints. 3659 * 3660 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to. 3661 * 3662 * @exception SWTException <ul> 3663 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3664 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3665 * </ul> 3666 * 3667 * @see #forceFocus 3668 */ 3669 public bool setFocus () { 3670 checkWidget(); 3671 if ((style & SWT.NO_FOCUS) !is 0) return false; 3672 return forceFocus (); 3673 } 3674 3675 /** 3676 * Sets the font that the receiver will use to paint textual information 3677 * to the font specified by the argument, or to the default font for that 3678 * kind of control if the argument is null. 3679 * 3680 * @param font the new font (or null) 3681 * 3682 * @exception IllegalArgumentException <ul> 3683 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 3684 * </ul> 3685 * @exception SWTException <ul> 3686 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3687 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3688 * </ul> 3689 */ 3690 public void setFont (Font font) { 3691 checkWidget(); 3692 if (((state & FONT) is 0) && font is null) return; 3693 this.font = font; 3694 PangoFontDescription* fontDesc; 3695 if (font is null) { 3696 fontDesc = defaultFont ().handle; 3697 } else { 3698 if (font.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); 3699 fontDesc = font.handle; 3700 } 3701 if (font is null) { 3702 state &= ~FONT; 3703 } else { 3704 state |= FONT; 3705 } 3706 setFontDescription (fontDesc); 3707 } 3708 3709 void setFontDescription (PangoFontDescription* font) { 3710 OS.gtk_widget_modify_font (handle, font); 3711 } 3712 3713 /** 3714 * Sets the receiver's foreground color to the color specified 3715 * by the argument, or to the default system color for the control 3716 * if the argument is null. 3717 * <p> 3718 * Note: This operation is a hint and may be overridden by the platform. 3719 * </p> 3720 * @param color the new color (or null) 3721 * 3722 * @exception IllegalArgumentException <ul> 3723 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 3724 * </ul> 3725 * @exception SWTException <ul> 3726 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3727 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3728 * </ul> 3729 */ 3730 public void setForeground (Color color) { 3731 checkWidget(); 3732 if (((state & FOREGROUND) is 0) && color is null) return; 3733 GdkColor* gdkColor = null; 3734 if (color !is null) { 3735 if (color.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); 3736 gdkColor = color.handle; 3737 } 3738 bool set = false; 3739 if (gdkColor is null) { 3740 auto style = OS.gtk_widget_get_modifier_style (handle); 3741 set = (OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_NORMAL) & OS.GTK_RC_FG) !is 0; 3742 } else { 3743 GdkColor* oldColor = getForegroundColor (); 3744 set = oldColor.pixel !is gdkColor.pixel; 3745 } 3746 if (set) { 3747 if (color is null) { 3748 state &= ~FOREGROUND; 3749 } else { 3750 state |= FOREGROUND; 3751 } 3752 setForegroundColor (gdkColor); 3753 } 3754 } 3755 3756 void setForegroundColor (GdkColor* color) { 3757 setForegroundColor (handle, color); 3758 } 3759 3760 void setInitialBounds () { 3761 if ((state & ZERO_WIDTH) !is 0 && (state & ZERO_HEIGHT) !is 0) { 3762 /* 3763 * Feature in GTK. On creation, each widget's allocation is 3764 * initialized to a position of (-1, -1) until the widget is 3765 * first sized. The fix is to set the value to (0, 0) as 3766 * expected by SWT. 3767 */ 3768 auto topHandle_ = topHandle (); 3769 if ((parent.style & SWT.MIRRORED) !is 0) { 3770 OS.GTK_WIDGET_SET_X (topHandle_, parent.getClientWidth ()); 3771 } else { 3772 OS.GTK_WIDGET_SET_X (topHandle_, 0); 3773 } 3774 OS.GTK_WIDGET_SET_Y (topHandle_, 0); 3775 } else { 3776 resizeHandle (1, 1); 3777 forceResize (); 3778 } 3779 } 3780 3781 /** 3782 * Sets the receiver's pop up menu to the argument. 3783 * All controls may optionally have a pop up 3784 * menu that is displayed when the user requests one for 3785 * the control. The sequence of key strokes, button presses 3786 * and/or button releases that are used to request a pop up 3787 * menu is platform specific. 3788 * <p> 3789 * Note: Disposing of a control that has a pop up menu will 3790 * dispose of the menu. To avoid this behavior, set the 3791 * menu to null before the control is disposed. 3792 * </p> 3793 * 3794 * @param menu the new pop up menu 3795 * 3796 * @exception IllegalArgumentException <ul> 3797 * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li> 3798 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li> 3799 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li> 3800 * </ul> 3801 * @exception SWTException <ul> 3802 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3803 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3804 * </ul> 3805 */ 3806 public void setMenu (Menu menu) { 3807 checkWidget(); 3808 if (menu !is null) { 3809 if ((menu.style & SWT.POP_UP) is 0) { 3810 error (SWT.ERROR_MENU_NOT_POP_UP); 3811 } 3812 if (menu.parent !is menuShell ()) { 3813 error (SWT.ERROR_INVALID_PARENT); 3814 } 3815 } 3816 this.menu = menu; 3817 } 3818 3819 override void setOrientation () { 3820 if ((style & SWT.RIGHT_TO_LEFT) !is 0) { 3821 if (handle !is null) OS.gtk_widget_set_direction (handle, OS.GTK_TEXT_DIR_RTL); 3822 if (fixedHandle !is null) OS.gtk_widget_set_direction (fixedHandle, OS.GTK_TEXT_DIR_RTL); 3823 } 3824 } 3825 3826 /** 3827 * Changes the parent of the widget to be the one provided if 3828 * the underlying operating system supports this feature. 3829 * Returns <code>true</code> if the parent is successfully changed. 3830 * 3831 * @param parent the new parent for the control. 3832 * @return <code>true</code> if the parent is changed and <code>false</code> otherwise. 3833 * 3834 * @exception IllegalArgumentException <ul> 3835 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 3836 * <li>ERROR_NULL_ARGUMENT - if the parent is <code>null</code></li> 3837 * </ul> 3838 * @exception SWTException <ul> 3839 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3840 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3841 * </ul> 3842 */ 3843 public bool setParent (Composite parent) { 3844 checkWidget (); 3845 if (parent is null) SWT.error (SWT.ERROR_NULL_ARGUMENT); 3846 if (parent.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT); 3847 if (this.parent is parent) return true; 3848 if (!isReparentable ()) return false; 3849 auto topHandle_ = topHandle (); 3850 int x = OS.GTK_WIDGET_X (topHandle_); 3851 int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); 3852 if ((this.parent.style & SWT.MIRRORED) !is 0) { 3853 x = this.parent.getClientWidth () - width - x; 3854 } 3855 if ((parent.style & SWT.MIRRORED) !is 0) { 3856 x = parent.getClientWidth () - width - x; 3857 } 3858 int y = OS.GTK_WIDGET_Y (topHandle_); 3859 releaseParent (); 3860 Shell newShell = parent.getShell (), oldShell = getShell (); 3861 Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell (); 3862 Menu [] menus = oldShell.findMenus (this); 3863 if (oldShell !is newShell || oldDecorations !is newDecorations) { 3864 fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus); 3865 newDecorations.fixAccelGroup (); 3866 oldDecorations.fixAccelGroup (); 3867 } 3868 auto newParent = parent.parentingHandle(); 3869 OS.gtk_widget_reparent (topHandle_, newParent); 3870 OS.gtk_fixed_move (cast(GtkFixed*)newParent, topHandle_, x, y); 3871 this.parent = parent; 3872 setZOrder (null, false, true); 3873 return true; 3874 } 3875 3876 void setParentBackground () { 3877 setBackgroundColor (handle, null); 3878 if (fixedHandle !is null) setBackgroundColor (fixedHandle, null); 3879 } 3880 3881 void setParentWindow (GtkWidget* widget) { 3882 } 3883 3884 bool setRadioSelection (bool value) { 3885 return false; 3886 } 3887 3888 /** 3889 * If the argument is <code>false</code>, causes subsequent drawing 3890 * operations in the receiver to be ignored. No drawing of any kind 3891 * can occur in the receiver until the flag is set to true. 3892 * Graphics operations that occurred while the flag was 3893 * <code>false</code> are lost. When the flag is set to <code>true</code>, 3894 * the entire widget is marked as needing to be redrawn. Nested calls 3895 * to this method are stacked. 3896 * <p> 3897 * Note: This operation is a hint and may not be supported on some 3898 * platforms or for some widgets. 3899 * </p> 3900 * 3901 * @param redraw the new redraw state 3902 * 3903 * @exception SWTException <ul> 3904 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3905 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3906 * </ul> 3907 * 3908 * @see #redraw(int, int, int, int, bool) 3909 * @see #update() 3910 */ 3911 public void setRedraw (bool redraw) { 3912 checkWidget(); 3913 if (redraw) { 3914 if (--drawCount is 0) { 3915 if (redrawWindow !is null) { 3916 auto window = paintWindow (); 3917 /* Explicitly hiding the window avoids flicker on GTK+ >= 2.6 */ 3918 OS.gdk_window_hide (redrawWindow); 3919 OS.gdk_window_destroy (redrawWindow); 3920 OS.gdk_window_set_events (window, OS.gtk_widget_get_events (paintHandle ())); 3921 redrawWindow = null; 3922 } 3923 } 3924 } else { 3925 if (drawCount++ is 0) { 3926 if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) !is 0) { 3927 auto window = paintWindow (); 3928 Rectangle rect = getBounds (); 3929 GdkWindowAttr attributes; 3930 attributes.width = rect.width; 3931 attributes.height = rect.height; 3932 attributes.event_mask = OS.GDK_EXPOSURE_MASK; 3933 attributes.window_type = OS.GDK_WINDOW_CHILD; 3934 redrawWindow = OS.gdk_window_new (window, &attributes, 0); 3935 if (redrawWindow !is null) { 3936 int mouseMask = OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK | 3937 OS.GDK_ENTER_NOTIFY_MASK | OS.GDK_LEAVE_NOTIFY_MASK | 3938 OS.GDK_POINTER_MOTION_MASK | OS.GDK_POINTER_MOTION_HINT_MASK | 3939 OS.GDK_BUTTON_MOTION_MASK | OS.GDK_BUTTON1_MOTION_MASK | 3940 OS.GDK_BUTTON2_MOTION_MASK | OS.GDK_BUTTON3_MOTION_MASK; 3941 OS.gdk_window_set_events (window, OS.gdk_window_get_events (window) & ~mouseMask); 3942 OS.gdk_window_set_back_pixmap (redrawWindow, null, false); 3943 OS.gdk_window_show (redrawWindow); 3944 } 3945 } 3946 } 3947 } 3948 } 3949 3950 bool setTabGroupFocus (bool next) { 3951 return setTabItemFocus (next); 3952 } 3953 bool setTabItemFocus (bool next) { 3954 if (!isShowing ()) return false; 3955 return forceFocus (); 3956 } 3957 3958 /** 3959 * Sets the receiver's tool tip text to the argument, which 3960 * may be null indicating that no tool tip text should be shown. 3961 * 3962 * @param str the new tool tip text (or null) 3963 * 3964 * @exception SWTException <ul> 3965 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 3966 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 3967 * </ul> 3968 */ 3969 public void setToolTipText (String str) { 3970 checkWidget(); 3971 setToolTipText (_getShell (), str); 3972 toolTipText = str; 3973 } 3974 3975 void setToolTipText (Shell shell, String newString) { 3976 if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) { 3977 /* 3978 * Feature in GTK. In order to prevent children widgets 3979 * from inheriting their parent's tooltip, the tooltip is 3980 * a set on a shell only. In order to force the shell tooltip 3981 * to update when a new tip string is set, the existing string 3982 * in the tooltip is set to null, followed by running a query. 3983 * The real tip text can then be set. 3984 * 3985 * Note that this will only run if the control for which the 3986 * tooltip is being set is the current control (i.e. the control 3987 * under the pointer). 3988 */ 3989 if (display.currentControl is this) { 3990 shell.setToolTipText (shell.handle, eventHandle (), newString); 3991 } 3992 } else { 3993 shell.setToolTipText (eventHandle (), newString); 3994 } 3995 } 3996 3997 /** 3998 * Marks the receiver as visible if the argument is <code>true</code>, 3999 * and marks it invisible otherwise. 4000 * <p> 4001 * If one of the receiver's ancestors is not visible or some 4002 * other condition makes the receiver not visible, marking 4003 * it visible may not actually cause it to be displayed. 4004 * </p> 4005 * 4006 * @param visible the new visibility state 4007 * 4008 * @exception SWTException <ul> 4009 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 4010 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 4011 * </ul> 4012 */ 4013 public void setVisible (bool visible) { 4014 checkWidget(); 4015 if (((state & HIDDEN) is 0) is visible) return; 4016 auto topHandle_ = topHandle(); 4017 if (visible) { 4018 /* 4019 * It is possible (but unlikely), that application 4020 * code could have disposed the widget in the show 4021 * event. If this happens, just return. 4022 */ 4023 sendEvent (SWT.Show); 4024 if (isDisposed ()) return; 4025 state &= ~HIDDEN; 4026 if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) is 0) { 4027 if (enableWindow !is null) OS.gdk_window_show_unraised (enableWindow); 4028 OS.gtk_widget_show (topHandle_); 4029 } 4030 } else { 4031 /* 4032 * Bug in GTK. Invoking gtk_widget_hide() on a widget that has 4033 * focus causes a focus_out_event to be sent. If the client disposes 4034 * the widget inside the event, GTK GP's. The fix is to reassign focus 4035 * before hiding the widget. 4036 * 4037 * NOTE: In order to stop the same widget from taking focus, 4038 * temporarily clear and set the GTK_VISIBLE flag. 4039 */ 4040 Control control = null; 4041 bool fixFocus_ = false; 4042 if (display.focusEvent !is SWT.FocusOut) { 4043 control = display.getFocusControl (); 4044 fixFocus_ = isFocusAncestor (control); 4045 } 4046 state |= HIDDEN; 4047 if (fixFocus_) { 4048 OS.GTK_WIDGET_UNSET_FLAGS (topHandle_, OS.GTK_VISIBLE); 4049 fixFocus (control); 4050 if (isDisposed ()) return; 4051 OS.GTK_WIDGET_SET_FLAGS (topHandle_, OS.GTK_VISIBLE); 4052 } 4053 OS.gtk_widget_hide (topHandle_); 4054 if (isDisposed ()) return; 4055 if (enableWindow !is null) OS.gdk_window_hide (enableWindow); 4056 sendEvent (SWT.Hide); 4057 } 4058 } 4059 4060 void setZOrder (Control sibling, bool above, bool fixRelations) { 4061 setZOrder (sibling, above, fixRelations, true); 4062 } 4063 4064 void setZOrder (Control sibling, bool above, bool fixRelations, bool fixChildren) { 4065 int index = 0, siblingIndex = 0, oldNextIndex = -1; 4066 Control[] children = null; 4067 if (fixRelations) { 4068 /* determine the receiver's and sibling's indexes in the parent */ 4069 children = parent._getChildren (); 4070 while (index < children.length) { 4071 if (children [index] is this) break; 4072 index++; 4073 } 4074 if (sibling !is null) { 4075 while (siblingIndex < children.length) { 4076 if (children [siblingIndex] is sibling) break; 4077 siblingIndex++; 4078 } 4079 } 4080 /* remove "Labelled by" relationships that will no longer be valid */ 4081 removeRelation (); 4082 if (index + 1 < children.length) { 4083 oldNextIndex = index + 1; 4084 children [oldNextIndex].removeRelation (); 4085 } 4086 if (sibling !is null) { 4087 if (above) { 4088 sibling.removeRelation (); 4089 } else { 4090 if (siblingIndex + 1 < children.length) { 4091 children [siblingIndex + 1].removeRelation (); 4092 } 4093 } 4094 } 4095 } 4096 4097 auto topHandle_ = topHandle (); 4098 auto siblingHandle = sibling !is null ? sibling.topHandle () : null; 4099 auto window = OS.GTK_WIDGET_WINDOW (topHandle_); 4100 if (window !is null) { 4101 GdkWindow* siblingWindow; 4102 if (sibling !is null) { 4103 if (above && sibling.enableWindow !is null) { 4104 siblingWindow = enableWindow; 4105 } else { 4106 siblingWindow = OS.GTK_WIDGET_WINDOW (siblingHandle); 4107 } 4108 } 4109 auto redrawWindow = fixChildren ? parent.redrawWindow : null; 4110 if (!OS.GDK_WINDOWING_X11 () || (siblingWindow is null && (!above || redrawWindow is null))) { 4111 if (above) { 4112 OS.gdk_window_raise (window); 4113 if (redrawWindow !is null) OS.gdk_window_raise (redrawWindow); 4114 if (enableWindow !is null) OS.gdk_window_raise (enableWindow); 4115 } else { 4116 if (enableWindow !is null) OS.gdk_window_lower (enableWindow); 4117 OS.gdk_window_lower (window); 4118 } 4119 } else { 4120 XWindowChanges changes; 4121 changes.sibling = OS.gdk_x11_drawable_get_xid (cast(GdkDrawable*)(siblingWindow !is null ? siblingWindow : redrawWindow)); 4122 changes.stack_mode = above ? OS.Above : OS.Below; 4123 if (redrawWindow !is null && siblingWindow is null) changes.stack_mode = OS.Below; 4124 auto xDisplay = OS.gdk_x11_drawable_get_xdisplay (cast(GdkDrawable*)window); 4125 auto xWindow = OS.gdk_x11_drawable_get_xid (cast(GdkDrawable*)window); 4126 int xScreen = OS.XDefaultScreen (xDisplay); 4127 int flags = OS.CWStackMode | OS.CWSibling; 4128 /* 4129 * Feature in X. If the receiver is a top level, XConfigureWindow () 4130 * will fail (with a BadMatch error) for top level shells because top 4131 * level shells are reparented by the window manager and do not share 4132 * the same X window parent. This is the correct behavior but it is 4133 * unexpected. The fix is to use XReconfigureWMWindow () instead. 4134 * When the receiver is not a top level shell, XReconfigureWMWindow () 4135 * behaves the same as XConfigureWindow (). 4136 */ 4137 OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, &changes); 4138 if (enableWindow !is null) { 4139 changes.sibling = OS.gdk_x11_drawable_get_xid (cast(GdkDrawable*)window); 4140 changes.stack_mode = OS.Above; 4141 xWindow = OS.gdk_x11_drawable_get_xid (cast(GdkDrawable*)enableWindow); 4142 OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, &changes); 4143 } 4144 } 4145 } 4146 if (fixChildren) { 4147 if (above) { 4148 parent.moveAbove (topHandle_, siblingHandle); 4149 } else { 4150 parent.moveBelow (topHandle_, siblingHandle); 4151 } 4152 } 4153 /* Make sure that the parent internal windows are on the bottom of the stack */ 4154 if (!above && fixChildren) parent.fixZOrder (); 4155 4156 if (fixRelations) { 4157 /* determine the receiver's new index in the parent */ 4158 if (sibling !is null) { 4159 if (above) { 4160 index = siblingIndex - (index < siblingIndex ? 1 : 0); 4161 } else { 4162 index = siblingIndex + (siblingIndex < index ? 1 : 0); 4163 } 4164 } else { 4165 if (above) { 4166 index = 0; 4167 } else { 4168 index = cast(int)/*64bit*/children.length - 1; 4169 } 4170 } 4171 4172 /* add new "Labelled by" relations as needed */ 4173 children = parent._getChildren (); 4174 if (0 < index) { 4175 children [index - 1].addRelation (this); 4176 } 4177 if (index + 1 < children.length) { 4178 addRelation (children [index + 1]); 4179 } 4180 if (oldNextIndex !is -1) { 4181 if (oldNextIndex <= index) oldNextIndex--; 4182 /* the last two conditions below ensure that duplicate relations are not hooked */ 4183 if (0 < oldNextIndex && oldNextIndex !is index && oldNextIndex !is index + 1) { 4184 children [oldNextIndex - 1].addRelation (children [oldNextIndex]); 4185 } 4186 } 4187 } 4188 } 4189 4190 void setWidgetBackground () { 4191 if (fixedHandle !is null) { 4192 auto style = OS.gtk_widget_get_modifier_style (fixedHandle); 4193 modifyStyle (fixedHandle, style); 4194 } 4195 auto style = OS.gtk_widget_get_modifier_style (handle); 4196 modifyStyle (handle, style); 4197 } 4198 4199 bool showMenu (int x, int y) { 4200 Event event = new Event (); 4201 event.x = x; 4202 event.y = y; 4203 sendEvent (SWT.MenuDetect, event); 4204 if (event.doit) { 4205 if (menu !is null && !menu.isDisposed ()) { 4206 bool hooksKeys = hooks (SWT.KeyDown) || hooks (SWT.KeyUp); 4207 menu.createIMMenu (hooksKeys ? imHandle() : null); 4208 if (event.x !is x || event.y !is y) { 4209 menu.setLocation (event.x, event.y); 4210 } 4211 menu.setVisible (true); 4212 return true; 4213 } 4214 } 4215 return false; 4216 } 4217 4218 void showWidget () { 4219 // Comment this line to disable zero-sized widgets 4220 state |= ZERO_WIDTH | ZERO_HEIGHT; 4221 auto topHandle_ = topHandle (); 4222 auto parentHandle = parent.parentingHandle (); 4223 parent.setParentWindow (topHandle_); 4224 OS.gtk_container_add (cast(GtkContainer*)parentHandle, topHandle_); 4225 if (handle !is null && handle !is topHandle_) OS.gtk_widget_show (handle); 4226 if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) is 0) { 4227 if (fixedHandle !is null) OS.gtk_widget_show (fixedHandle); 4228 } 4229 if (fixedHandle !is null) fixStyle (fixedHandle); 4230 } 4231 4232 void sort (int [] items) { 4233 /* Shell Sort from K&R, pg 108 */ 4234 ptrdiff_t length = items.length; 4235 for (ptrdiff_t gap=length/2; gap>0; gap/=2) { 4236 for (ptrdiff_t i=gap; i<length; i++) { 4237 for (ptrdiff_t j=i-gap; j>=0; j-=gap) { 4238 if (items [j] <= items [j + gap]) { 4239 int swap = items [j]; 4240 items [j] = items [j + gap]; 4241 items [j + gap] = swap; 4242 } 4243 } 4244 } 4245 } 4246 } 4247 4248 /** 4249 * Based on the argument, perform one of the expected platform 4250 * traversal action. The argument should be one of the constants: 4251 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>, 4252 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>, 4253 * <code>SWT.TRAVERSE_ARROW_NEXT</code> and <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>. 4254 * 4255 * @param traversal the type of traversal 4256 * @return true if the traversal succeeded 4257 * 4258 * @exception SWTException <ul> 4259 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 4260 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 4261 * </ul> 4262 */ 4263 public bool traverse (int traversal) { 4264 checkWidget (); 4265 Event event = new Event (); 4266 event.doit = true; 4267 event.detail = traversal; 4268 return traverse (event); 4269 } 4270 4271 bool translateMnemonic (Event event, Control control) { 4272 if (control is this) return false; 4273 if (!isVisible () || !isEnabled ()) return false; 4274 event.doit = this is display.mnemonicControl || mnemonicMatch (event.character); 4275 return traverse (event); 4276 } 4277 4278 bool translateMnemonic (int keyval, GdkEventKey* gdkEvent) { 4279 int key = OS.gdk_keyval_to_unicode (keyval); 4280 if (key < 0x20) return false; 4281 if (gdkEvent.state is 0) { 4282 int code = traversalCode (keyval, gdkEvent); 4283 if ((code & SWT.TRAVERSE_MNEMONIC) is 0) return false; 4284 } else { 4285 Shell shell = _getShell (); 4286 int mask = OS.GDK_CONTROL_MASK | OS.GDK_SHIFT_MASK | OS.GDK_MOD1_MASK; 4287 if ((gdkEvent.state & mask) !is OS.gtk_window_get_mnemonic_modifier (cast(GtkWindow*)shell.shellHandle)) return false; 4288 } 4289 Decorations shell = menuShell (); 4290 if (shell.isVisible () && shell.isEnabled ()) { 4291 Event event = new Event (); 4292 event.detail = SWT.TRAVERSE_MNEMONIC; 4293 if (setKeyState (event, gdkEvent)) { 4294 return translateMnemonic (event, null) || shell.translateMnemonic (event, this); 4295 } 4296 } 4297 return false; 4298 } 4299 4300 bool translateTraversal (GdkEventKey* keyEvent) { 4301 int detail = SWT.TRAVERSE_NONE; 4302 int key = keyEvent.keyval; 4303 int code = traversalCode (key, keyEvent); 4304 bool all = false; 4305 switch (key) { 4306 case OS.GDK_Escape: { 4307 all = true; 4308 detail = SWT.TRAVERSE_ESCAPE; 4309 break; 4310 } 4311 case OS.GDK_KP_Enter: 4312 case OS.GDK_Return: { 4313 all = true; 4314 detail = SWT.TRAVERSE_RETURN; 4315 break; 4316 } 4317 case OS.GDK_ISO_Left_Tab: 4318 case OS.GDK_Tab: { 4319 bool next = (keyEvent.state & OS.GDK_SHIFT_MASK) is 0; 4320 detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS; 4321 break; 4322 } 4323 case OS.GDK_Up: 4324 case OS.GDK_Left: 4325 case OS.GDK_Down: 4326 case OS.GDK_Right: { 4327 bool next = key is OS.GDK_Down || key is OS.GDK_Right; 4328 if (parent !is null && (parent.style & SWT.MIRRORED) !is 0) { 4329 if (key is OS.GDK_Left || key is OS.GDK_Right) next = !next; 4330 } 4331 detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS; 4332 break; 4333 } 4334 case OS.GDK_Page_Up: 4335 case OS.GDK_Page_Down: { 4336 all = true; 4337 if ((keyEvent.state & OS.GDK_CONTROL_MASK) is 0) return false; 4338 detail = key is OS.GDK_Page_Down ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS; 4339 break; 4340 } 4341 default: 4342 return false; 4343 } 4344 Event event = new Event (); 4345 event.doit = (code & detail) !is 0; 4346 event.detail = detail; 4347 event.time = keyEvent.time; 4348 if (!setKeyState (event, keyEvent)) return false; 4349 Shell shell = getShell (); 4350 Control control = this; 4351 do { 4352 if (control.traverse (event)) return true; 4353 if (!event.doit && control.hooks (SWT.Traverse)) return false; 4354 if (control is shell) return false; 4355 control = control.parent; 4356 } while (all && control !is null); 4357 return false; 4358 } 4359 4360 int traversalCode (int key, GdkEventKey* event) { 4361 int code = SWT.TRAVERSE_RETURN | SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_PAGE_NEXT | SWT.TRAVERSE_PAGE_PREVIOUS; 4362 Shell shell = getShell (); 4363 if (shell.parent !is null) code |= SWT.TRAVERSE_ESCAPE; 4364 return code; 4365 } 4366 4367 bool traverse (Event event) { 4368 /* 4369 * It is possible (but unlikely), that application 4370 * code could have disposed the widget in the traverse 4371 * event. If this happens, return true to stop further 4372 * event processing. 4373 */ 4374 sendEvent (SWT.Traverse, event); 4375 if (isDisposed ()) return true; 4376 if (!event.doit) return false; 4377 switch (event.detail) { 4378 case SWT.TRAVERSE_NONE: return true; 4379 case SWT.TRAVERSE_ESCAPE: return traverseEscape (); 4380 case SWT.TRAVERSE_RETURN: return traverseReturn (); 4381 case SWT.TRAVERSE_TAB_NEXT: return traverseGroup (true); 4382 case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false); 4383 case SWT.TRAVERSE_ARROW_NEXT: return traverseItem (true); 4384 case SWT.TRAVERSE_ARROW_PREVIOUS: return traverseItem (false); 4385 case SWT.TRAVERSE_MNEMONIC: return traverseMnemonic (cast(char) event.character); 4386 case SWT.TRAVERSE_PAGE_NEXT: return traversePage (true); 4387 case SWT.TRAVERSE_PAGE_PREVIOUS: return traversePage (false); 4388 default: 4389 } 4390 return false; 4391 } 4392 4393 bool traverseEscape () { 4394 return false; 4395 } 4396 4397 bool traverseGroup (bool next) { 4398 Control root = computeTabRoot (); 4399 Control group = computeTabGroup (); 4400 Control [] list = root.computeTabList (); 4401 ptrdiff_t length = list.length; 4402 ptrdiff_t index = 0; 4403 while (index < length) { 4404 if (list [index] is group) break; 4405 index++; 4406 } 4407 /* 4408 * It is possible (but unlikely), that application 4409 * code could have disposed the widget in focus in 4410 * or out events. Ensure that a disposed widget is 4411 * not accessed. 4412 */ 4413 if (index is length) return false; 4414 ptrdiff_t start = index, offset = (next) ? 1 : -1; 4415 while ((index = ((index + offset + length) % length)) !is start) { 4416 Control control = list [index]; 4417 if (!control.isDisposed () && control.setTabGroupFocus (next)) { 4418 return true; 4419 } 4420 } 4421 if (group.isDisposed ()) return false; 4422 return group.setTabGroupFocus (next); 4423 } 4424 4425 bool traverseItem (bool next) { 4426 Control [] children = parent._getChildren (); 4427 ptrdiff_t length = children.length; 4428 ptrdiff_t index = 0; 4429 while (index < length) { 4430 if (children [index] is this) break; 4431 index++; 4432 } 4433 /* 4434 * It is possible (but unlikely), that application 4435 * code could have disposed the widget in focus in 4436 * or out events. Ensure that a disposed widget is 4437 * not accessed. 4438 */ 4439 if (index is length) return false; 4440 ptrdiff_t start = index, offset = (next) ? 1 : -1; 4441 while ((index = (index + offset + length) % length) !is start) { 4442 Control child = children [index]; 4443 if (!child.isDisposed () && child.isTabItem ()) { 4444 if (child.setTabItemFocus (next)) return true; 4445 } 4446 } 4447 return false; 4448 } 4449 4450 bool traverseReturn () { 4451 return false; 4452 } 4453 4454 bool traversePage (bool next) { 4455 return false; 4456 } 4457 4458 bool traverseMnemonic (char key) { 4459 return mnemonicHit (key); 4460 } 4461 4462 /** 4463 * Forces all outstanding paint requests for the widget 4464 * to be processed before this method returns. If there 4465 * are no outstanding paint request, this method does 4466 * nothing. 4467 * <p> 4468 * Note: This method does not cause a redraw. 4469 * </p> 4470 * 4471 * @exception SWTException <ul> 4472 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 4473 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 4474 * </ul> 4475 * 4476 * @see #redraw() 4477 * @see #redraw(int, int, int, int, bool) 4478 * @see PaintListener 4479 * @see SWT#Paint 4480 */ 4481 public void update () { 4482 checkWidget (); 4483 update (false, true); 4484 } 4485 4486 void update (bool all, bool flush) { 4487 // checkWidget(); 4488 if (!OS.GTK_WIDGET_VISIBLE (topHandle ())) return; 4489 if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) is 0) return; 4490 auto window = paintWindow (); 4491 if (flush) display.flushExposes (window, all); 4492 OS.gdk_window_process_updates (window, all); 4493 OS.gdk_flush (); 4494 } 4495 4496 void updateBackgroundMode () { 4497 int oldState = state & PARENT_BACKGROUND; 4498 checkBackground (); 4499 if (oldState !is (state & PARENT_BACKGROUND)) { 4500 setBackground (); 4501 } 4502 } 4503 4504 void updateLayout (bool all) { 4505 /* Do nothing */ 4506 } 4507 4508 override int windowProc (GtkWidget* handle, ptrdiff_t arg0, ptrdiff_t user_data) { 4509 switch (user_data) { 4510 case EXPOSE_EVENT_INVERSE: { 4511 if ((OS.GTK_VERSION < OS.buildVERSION (2, 8, 0)) && ((state & OBSCURED) is 0)) { 4512 Control control = findBackgroundControl (); 4513 if (control !is null && control.backgroundImage !is null) { 4514 GdkEventExpose* gdkEvent = cast(GdkEventExpose*)arg0; 4515 auto paintWindow = paintWindow(); 4516 auto window = gdkEvent.window; 4517 if (window !is paintWindow) break; 4518 auto gdkGC = OS.gdk_gc_new (cast(GdkDrawable*)window); 4519 OS.gdk_gc_set_clip_region (gdkGC, gdkEvent.region); 4520 int dest_x, dest_y; 4521 OS.gtk_widget_translate_coordinates (paintHandle (), control.paintHandle (), 0, 0, &dest_x, &dest_y); 4522 OS.gdk_gc_set_fill (gdkGC, OS.GDK_TILED); 4523 OS.gdk_gc_set_ts_origin (gdkGC, -dest_x, -dest_y); 4524 OS.gdk_gc_set_tile (gdkGC, cast(GdkPixmap*)control.backgroundImage.pixmap); 4525 OS.gdk_draw_rectangle (cast(GdkDrawable*)window, gdkGC, 1, gdkEvent.area.x, gdkEvent.area.y, gdkEvent.area.width, gdkEvent.area.height); 4526 OS.g_object_unref (gdkGC); 4527 } 4528 } 4529 break; 4530 default: 4531 } 4532 } 4533 return super.windowProc (handle, arg0, user_data); 4534 } 4535 }