1 /*
   2  * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "awt_ScrollPane.h"
  27 
  28 #include "awt_Container.h"
  29 #include "awt_Insets.h"
  30 #include "awt_Panel.h"
  31 #include "awt_Scrollbar.h"   // static #defines
  32 #include "awt_Toolkit.h"
  33 #include "awt_Window.h"
  34 
  35 #include <java_awt_Adjustable.h>
  36 #include <java_awt_ScrollPane.h>
  37 #include <java_awt_ScrollPaneAdjustable.h>
  38 #include <java_awt_event_AdjustmentEvent.h>
  39 
  40 
  41 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
  42  */
  43 
  44 /***********************************************************************/
  45 // struct for _GetOffset() method
  46 struct GetOffsetStruct {
  47     jobject scrollpane;
  48     jint orient;
  49 };
  50 // struct for _SetScrollPos() method
  51 struct SetScrollPosStruct {
  52     jobject scrollpane;
  53     jint x, y;
  54 };
  55 // struct for _SetSpans() method
  56 struct SetSpansStruct {
  57     jobject scrollpane;
  58     jint parentWidth;
  59     jint parentHeight;
  60     jint childWidth;
  61     jint childHeight;
  62 };
  63 /************************************************************************
  64  * AwtScrollPane fields
  65  */
  66 
  67 jfieldID AwtScrollPane::scrollbarDisplayPolicyID;
  68 jfieldID AwtScrollPane::hAdjustableID;
  69 jfieldID AwtScrollPane::vAdjustableID;
  70 jfieldID AwtScrollPane::unitIncrementID;
  71 jfieldID AwtScrollPane::blockIncrementID;
  72 jmethodID AwtScrollPane::postScrollEventID;
  73 
  74 /************************************************************************
  75  * AwtScrollPane methods
  76  */
  77 
  78 AwtScrollPane::AwtScrollPane() {
  79 }
  80 
  81 LPCTSTR AwtScrollPane::GetClassName() {
  82     return TEXT("SunAwtScrollPane");
  83 }
  84 
  85 /* Create a new AwtScrollPane object and window.   */
  86 AwtScrollPane* AwtScrollPane::Create(jobject self, jobject parent)
  87 {
  88     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
  89     jobject target = NULL;
  90     AwtScrollPane* c = NULL;
  91 
  92     try {
  93         if (env->EnsureLocalCapacity(1) < 0) {
  94             return NULL;
  95         }
  96 
  97         PDATA pData;
  98         AwtComponent* awtParent;
  99 
 100         JNI_CHECK_PEER_GOTO(parent, done);
 101         awtParent = (AwtComponent*)pData;
 102 
 103         target = env->GetObjectField(self, AwtObject::targetID);
 104         JNI_CHECK_NULL_GOTO(target, "null target", done);
 105 
 106         c = new AwtScrollPane();
 107 
 108         {
 109             DWORD style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
 110             jint scrollbarDisplayPolicy =
 111                 env->GetIntField(target, scrollbarDisplayPolicyID);
 112 
 113             if (scrollbarDisplayPolicy
 114                     == java_awt_ScrollPane_SCROLLBARS_ALWAYS) {
 115                 style |= WS_HSCROLL | WS_VSCROLL;
 116             }
 117             DWORD exStyle = WS_EX_CLIENTEDGE;
 118 
 119             if (GetRTL()) {
 120                 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
 121                 if (GetRTLReadingOrder())
 122                     exStyle |= WS_EX_RTLREADING;
 123             }
 124 
 125             jint x = env->GetIntField(target, AwtComponent::xID);
 126             jint y = env->GetIntField(target, AwtComponent::yID);
 127             jint width = env->GetIntField(target, AwtComponent::widthID);
 128             jint height = env->GetIntField(target, AwtComponent::heightID);
 129             c->CreateHWnd(env, L"", style, exStyle,
 130                           x, y, width, height,
 131                           awtParent->GetHWnd(),
 132                           reinterpret_cast<HMENU>(static_cast<INT_PTR>(
 133                 awtParent->CreateControlID())),
 134                           ::GetSysColor(COLOR_WINDOWTEXT),
 135                           ::GetSysColor(COLOR_WINDOW),
 136                           self);
 137         }
 138     } catch (...) {
 139         env->DeleteLocalRef(target);
 140         throw;
 141     }
 142 
 143 done:
 144     env->DeleteLocalRef(target);
 145     return c;
 146 }
 147 
 148 void AwtScrollPane::SetInsets(JNIEnv *env)
 149 {
 150     RECT outside;
 151     RECT inside;
 152     ::GetWindowRect(GetHWnd(), &outside);
 153     ::GetClientRect(GetHWnd(), &inside);
 154     ::MapWindowPoints(GetHWnd(), 0, (LPPOINT)&inside, 2);
 155 
 156     if (env->EnsureLocalCapacity(1) < 0) {
 157         return;
 158     }
 159     jobject insets =
 160       (env)->GetObjectField(GetPeer(env), AwtPanel::insets_ID);
 161 
 162     DASSERT(!safe_ExceptionOccurred(env));
 163 
 164     if (insets != NULL && (inside.top-outside.top) != 0) {
 165         (env)->SetIntField(insets, AwtInsets::topID, inside.top - outside.top);
 166         (env)->SetIntField(insets, AwtInsets::leftID, inside.left - outside.left);
 167         (env)->SetIntField(insets, AwtInsets::bottomID, outside.bottom - inside.bottom);
 168         (env)->SetIntField(insets, AwtInsets::rightID, outside.right - inside.right);
 169     }
 170 
 171     env->DeleteLocalRef(insets);
 172 }
 173 
 174 void AwtScrollPane::SetScrollInfo(int orient, int max, int page,
 175                                   BOOL disableNoScroll)
 176 {
 177     DTRACE_PRINTLN4("AwtScrollPane::SetScrollInfo %d, %d, %d, %d", orient, max, page, disableNoScroll);
 178     SCROLLINFO si;
 179     int posBefore;
 180     int posAfter;
 181 
 182     posBefore = GetScrollPos(orient);
 183     si.cbSize = sizeof(SCROLLINFO);
 184     si.nMin = 0;
 185     si.nMax = max;
 186     si.fMask = SIF_RANGE;
 187     if (disableNoScroll) {
 188         si.fMask |= SIF_DISABLENOSCROLL;
 189     }
 190     if (page > 0) {
 191         si.fMask |= SIF_PAGE;
 192         si.nPage = page;
 193     }
 194     ::SetScrollInfo(GetHWnd(), orient, &si, TRUE);
 195     // scroll position may have changed when thumb is at the end of the bar
 196     // and the page size changes
 197     posAfter = GetScrollPos(orient);
 198     if (posBefore != posAfter) {
 199         PostScrollEvent(orient, SB_THUMBPOSITION, posAfter);
 200     }
 201 }
 202 
 203 void AwtScrollPane::RecalcSizes(int parentWidth, int parentHeight,
 204                                 int childWidth, int childHeight)
 205 {
 206     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 207     if (env->EnsureLocalCapacity(2) < 0) {
 208         return;
 209     }
 210 
 211     /* Determine border width without scrollbars. */
 212     int horzBorder = ::GetSystemMetrics(SM_CXEDGE);;
 213     int vertBorder = ::GetSystemMetrics(SM_CYEDGE);;
 214 
 215     parentWidth -= (horzBorder * 2);
 216     parentHeight -= (vertBorder * 2);
 217 
 218     /* Enable each scrollbar as needed. */
 219     jobject target = AwtObject::GetTarget(env);
 220     jint policy = env->GetIntField(target,
 221                                    AwtScrollPane::scrollbarDisplayPolicyID);
 222 
 223     BOOL needsHorz=(policy == java_awt_ScrollPane_SCROLLBARS_ALWAYS ||
 224                     (policy == java_awt_ScrollPane_SCROLLBARS_AS_NEEDED &&
 225                      childWidth > parentWidth));
 226     if (needsHorz) {
 227         parentHeight -= ::GetSystemMetrics(SM_CYHSCROLL);
 228     }
 229     BOOL needsVert=(policy == java_awt_ScrollPane_SCROLLBARS_ALWAYS ||
 230                     (policy ==java_awt_ScrollPane_SCROLLBARS_AS_NEEDED &&
 231                      childHeight > parentHeight));
 232     if (needsVert) {
 233         parentWidth -= ::GetSystemMetrics(SM_CXVSCROLL);
 234     }
 235     /*
 236      * Since the vertical scrollbar may have reduced the parent width
 237      * enough to now require a horizontal scrollbar, we need to
 238      * recalculate the horizontal metrics and scrollbar boolean.
 239      */
 240     if (!needsHorz) {
 241         needsHorz = (policy == java_awt_ScrollPane_SCROLLBARS_ALWAYS ||
 242                      (policy == java_awt_ScrollPane_SCROLLBARS_AS_NEEDED &&
 243                       childWidth > parentWidth));
 244         if (needsHorz) {
 245             parentHeight -= ::GetSystemMetrics(SM_CYHSCROLL);
 246         }
 247     }
 248 
 249     /* Now set ranges -- setting the min and max the same disables them. */
 250     if (needsHorz) {
 251         jobject hAdj =
 252             env->GetObjectField(target, AwtScrollPane::hAdjustableID);
 253         env->SetIntField(hAdj, AwtScrollPane::blockIncrementID, parentWidth);
 254         SetScrollInfo(SB_HORZ, childWidth - 1, parentWidth,
 255                       (policy == java_awt_ScrollPane_SCROLLBARS_ALWAYS));
 256         env->DeleteLocalRef(hAdj);
 257     } else {
 258         /* Set scroll info to imitate the behaviour and since we don't
 259             need to display it, explicitly don't show the bar */
 260         SetScrollInfo(SB_HORZ, childWidth - 1, parentWidth,
 261                       (policy == java_awt_ScrollPane_SCROLLBARS_ALWAYS));
 262         ::ShowScrollBar(GetHWnd(), SB_HORZ, false);
 263     }
 264 
 265     if (needsVert) {
 266         jobject vAdj =
 267             env->GetObjectField(target, AwtScrollPane::vAdjustableID);
 268         env->SetIntField(vAdj, AwtScrollPane::blockIncrementID, parentHeight);
 269         SetScrollInfo(SB_VERT, childHeight - 1, parentHeight,
 270                       (policy == java_awt_ScrollPane_SCROLLBARS_ALWAYS));
 271         env->DeleteLocalRef(vAdj);
 272     } else {
 273         /* Set scroll info to imitate the behaviour and since we don't
 274             need to display it, explicitly don't show the bar */
 275         SetScrollInfo(SB_VERT, childHeight - 1, parentHeight,
 276                       (policy == java_awt_ScrollPane_SCROLLBARS_ALWAYS));
 277         ::ShowScrollBar(GetHWnd(), SB_VERT, false);
 278     }
 279 
 280     env->DeleteLocalRef(target);
 281 }
 282 
 283 void AwtScrollPane::Reshape(int x, int y, int w, int h)
 284 {
 285     AwtComponent::Reshape(x, y, w, h);
 286 }
 287 
 288 void AwtScrollPane::Show(JNIEnv *env)
 289 {
 290     SetInsets(env);
 291     SendMessage(WM_AWT_COMPONENT_SHOW);
 292 }
 293 
 294 void AwtScrollPane::PostScrollEvent(int orient, int scrollCode, int pos) {
 295     if (scrollCode == SB_ENDSCROLL) {
 296         return;
 297     }
 298 
 299     // convert Windows scroll bar ident to peer ident
 300     jint jorient;
 301     if (orient == SB_VERT) {
 302         jorient = java_awt_Adjustable_VERTICAL;
 303     } else if (orient == SB_HORZ) {
 304         jorient = java_awt_Adjustable_HORIZONTAL;
 305     } else {
 306         DASSERT(FALSE);
 307         return;
 308     }
 309 
 310     // convert Windows scroll code to adjustment type and isAdjusting status
 311     jint jscrollcode;
 312     jboolean jadjusting = JNI_FALSE;
 313     SCROLLINFO si;
 314     switch (scrollCode) {
 315       case SB_LINEUP:
 316           jscrollcode = java_awt_event_AdjustmentEvent_UNIT_DECREMENT;
 317           break;
 318       case SB_LINEDOWN:
 319           jscrollcode = java_awt_event_AdjustmentEvent_UNIT_INCREMENT;
 320           break;
 321       case SB_PAGEUP:
 322           jscrollcode = java_awt_event_AdjustmentEvent_BLOCK_DECREMENT;
 323           break;
 324       case SB_PAGEDOWN:
 325           jscrollcode = java_awt_event_AdjustmentEvent_BLOCK_INCREMENT;
 326           break;
 327       case SB_TOP:
 328           jscrollcode = java_awt_event_AdjustmentEvent_TRACK;
 329           ZeroMemory(&si, sizeof(si));
 330           si.cbSize = sizeof(si);
 331           si.fMask = SIF_RANGE;
 332           ::GetScrollInfo(GetHWnd(), orient, &si);
 333           pos = si.nMin;
 334           break;
 335       case SB_BOTTOM:
 336           jscrollcode = java_awt_event_AdjustmentEvent_TRACK;
 337           ZeroMemory(&si, sizeof(si));
 338           si.cbSize = sizeof(si);
 339           si.fMask = SIF_RANGE;
 340           ::GetScrollInfo(GetHWnd(), orient, &si);
 341           pos = si.nMax;
 342           break;
 343       case SB_THUMBTRACK:
 344           jscrollcode = java_awt_event_AdjustmentEvent_TRACK;
 345           jadjusting = JNI_TRUE;
 346           break;
 347       case SB_THUMBPOSITION:
 348           jscrollcode = java_awt_event_AdjustmentEvent_TRACK;
 349           break;
 350       default:
 351           DASSERT(FALSE);
 352           return;
 353     }
 354 
 355     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 356     env->CallVoidMethod(GetPeer(env), AwtScrollPane::postScrollEventID,
 357                         jorient, jscrollcode, (jint)pos, jadjusting);
 358     DASSERT(!safe_ExceptionOccurred(env));
 359 }
 360 
 361 MsgRouting
 362 AwtScrollPane::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
 363 {
 364     if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) {
 365         retVal = HTCLIENT;
 366         return mrConsume;
 367     }
 368     return AwtCanvas::WmNcHitTest(x, y, retVal);
 369 }
 370 
 371 MsgRouting AwtScrollPane::WmVScroll(UINT scrollCode, UINT pos, HWND hScrollPane)
 372 {
 373     // While user scrolls using tracker, SCROLLINFO.nPos is not changed, SCROLLINFO.nTrackPos is changed instead.
 374     int dragP = scrollCode == SB_THUMBPOSITION || scrollCode == SB_THUMBTRACK;
 375     int newPos = GetScrollPos(SB_VERT);
 376     if ( dragP ) {
 377         SCROLLINFO si;
 378         ZeroMemory(&si, sizeof(si));
 379         si.cbSize = sizeof(si);
 380         si.fMask = SIF_TRACKPOS;
 381         ::GetScrollInfo(GetHWnd(), SB_VERT, &si);
 382         newPos = si.nTrackPos;
 383     }
 384     PostScrollEvent(SB_VERT, scrollCode, newPos);
 385     return mrConsume;
 386 }
 387 
 388 MsgRouting AwtScrollPane::WmHScroll(UINT scrollCode, UINT pos, HWND hScrollPane)
 389 {
 390     // While user scrolls using tracker, SCROLLINFO.nPos is not changed, SCROLLINFO.nTrackPos is changed instead.
 391     int dragP = scrollCode == SB_THUMBPOSITION || scrollCode == SB_THUMBTRACK;
 392     int newPos = GetScrollPos(SB_HORZ);
 393     if ( dragP ) {
 394         SCROLLINFO si;
 395         ZeroMemory(&si, sizeof(si));
 396         si.cbSize = sizeof(si);
 397         si.fMask = SIF_TRACKPOS;
 398         ::GetScrollInfo(GetHWnd(), SB_HORZ, &si);
 399         newPos = si.nTrackPos;
 400     }
 401     PostScrollEvent(SB_HORZ, scrollCode, newPos);
 402     return mrConsume;
 403 }
 404 
 405 MsgRouting AwtScrollPane::HandleEvent(MSG *msg, BOOL synthetic)
 406 {
 407     // SunAwtScrollPane control doesn't cause activation on mouse/key events,
 408     // so we can safely (for synthetic focus) pass them to the system proc.
 409     return AwtComponent::HandleEvent(msg, synthetic);
 410 }
 411 
 412 int AwtScrollPane::GetScrollPos(int orient)
 413 {
 414     SCROLLINFO si;
 415     ZeroMemory(&si, sizeof(si));
 416     si.cbSize = sizeof(si);
 417     si.fMask = SIF_POS;
 418     ::GetScrollInfo(GetHWnd(), orient, &si);
 419     return si.nPos;
 420 }
 421 
 422 jint AwtScrollPane::_GetOffset(void *param)
 423 {
 424     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 425 
 426     GetOffsetStruct *gos = (GetOffsetStruct *)param;
 427     jobject self = gos->scrollpane;
 428     jint orient = gos->orient;
 429 
 430     jint result = 0;
 431     AwtScrollPane *s = NULL;
 432 
 433     PDATA pData;
 434     JNI_CHECK_PEER_GOTO(self, ret);
 435     s = (AwtScrollPane *)pData;
 436     if (::IsWindow(s->GetHWnd()))
 437     {
 438         DTRACE_PRINTLN2("%x: WScrollPanePeer.getOffset(%d)", self, orient);
 439         s->VerifyState();
 440         int nBar = (orient == java_awt_Adjustable_HORIZONTAL) ? SB_HORZ : SB_VERT;
 441         result = s->GetScrollPos(nBar);
 442     }
 443 ret:
 444    env->DeleteGlobalRef(self);
 445 
 446    delete gos;
 447 
 448    return result;
 449 }
 450 
 451 void AwtScrollPane::_SetInsets(void *param)
 452 {
 453     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 454 
 455     jobject self = (jobject)param;
 456 
 457     AwtScrollPane *s = NULL;
 458 
 459     PDATA pData;
 460     JNI_CHECK_PEER_GOTO(self, ret);
 461     s = (AwtScrollPane *)pData;
 462     if (::IsWindow(s->GetHWnd()))
 463     {
 464         DTRACE_PRINTLN1("%x: WScrollPanePeer.setInsets()", self);
 465         s->SetInsets(env);
 466         s->VerifyState();
 467     }
 468 ret:
 469    env->DeleteGlobalRef(self);
 470 }
 471 
 472 void AwtScrollPane::_SetScrollPos(void *param)
 473 {
 474     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 475 
 476     SetScrollPosStruct *spss = (SetScrollPosStruct *)param;
 477     jobject self = spss->scrollpane;
 478     jint x = spss->x;
 479     jint y = spss->y;
 480 
 481     AwtScrollPane *s = NULL;
 482 
 483     PDATA pData;
 484     JNI_CHECK_PEER_GOTO(self, ret);
 485     s = (AwtScrollPane *)pData;
 486     if (::IsWindow(s->GetHWnd()))
 487     {
 488         DTRACE_PRINTLN3("%x: WScrollPanePeer.setScrollPosition(%d, %d)", self, x, y);
 489         SCROLLINFO si;
 490         ZeroMemory(&si, sizeof(si));
 491         si.fMask = SIF_POS;
 492         si.cbSize = sizeof(si);
 493         // set x
 494         si.nPos = x;
 495         ::SetScrollInfo(s->GetHWnd(), SB_HORZ, &si, TRUE);
 496         // set y
 497         si.nPos = y;
 498         ::SetScrollInfo(s->GetHWnd(), SB_VERT, &si, TRUE);
 499     }
 500 ret:
 501    env->DeleteGlobalRef(self);
 502 
 503    delete spss;
 504 }
 505 
 506 void AwtScrollPane::_SetSpans(void *param)
 507 {
 508     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 509 
 510     SetSpansStruct *sss = (SetSpansStruct *)param;
 511     jobject self = sss->scrollpane;
 512     jint parentWidth = sss->parentWidth;
 513     jint parentHeight = sss->parentHeight;
 514     jint childWidth = sss->childWidth;
 515     jint childHeight = sss->childHeight;
 516 
 517     AwtScrollPane *s = NULL;
 518 
 519     PDATA pData;
 520     JNI_CHECK_PEER_GOTO(self, ret);
 521     s = (AwtScrollPane *)pData;
 522     if (::IsWindow(s->GetHWnd()))
 523     {
 524         DTRACE_PRINTLN5("%x: WScrollPanePeer.setSpans(%d, %d, %d, %d)", self,
 525             parentWidth, parentHeight, childWidth, childHeight);
 526         s->RecalcSizes(parentWidth, parentHeight, childWidth, childHeight);
 527         s->VerifyState();
 528     }
 529 ret:
 530    env->DeleteGlobalRef(self);
 531 
 532    delete sss;
 533 }
 534 
 535 #ifdef DEBUG
 536 void AwtScrollPane::VerifyState()
 537 {
 538     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 539     if (env->EnsureLocalCapacity(3) < 0) {
 540         return;
 541     }
 542 
 543     if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
 544         return;
 545     }
 546 
 547     if (m_callbacksEnabled == FALSE) {
 548         /* Component is not fully setup yet. */
 549         return;
 550     }
 551 
 552     AwtComponent::VerifyState();
 553 
 554     jobject target = AwtObject::GetTarget(env);
 555     jobject child = JNU_CallMethodByName(env, NULL, GetPeer(env),
 556                                          "getScrollSchild",
 557                                          "()Ljava/awt/Component;").l;
 558 
 559     DASSERT(!safe_ExceptionOccurred(env));
 560 
 561     if (child != NULL) {
 562         jobject childPeer =
 563             (env)->GetObjectField(child, AwtComponent::peerID);
 564         PDATA pData;
 565         JNI_CHECK_PEER_RETURN(childPeer);
 566         AwtComponent* awtChild = (AwtComponent *)pData;
 567 
 568         /* Verify child window is positioned correctly. */
 569         RECT rect, childRect;
 570         ::GetClientRect(GetHWnd(), &rect);
 571         ::MapWindowPoints(GetHWnd(), 0, (LPPOINT)&rect, 2);
 572         ::GetWindowRect(awtChild->GetHWnd(), &childRect);
 573         DASSERT(childRect.left <= rect.left && childRect.top <= rect.top);
 574 
 575         env->DeleteLocalRef(childPeer);
 576     }
 577     env->DeleteLocalRef(target);
 578     env->DeleteLocalRef(child);
 579 }
 580 #endif
 581 
 582 /************************************************************************
 583  * ScrollPane native methods
 584  */
 585 
 586 extern "C" {
 587 
 588 /*
 589  * Class:     java_awt_ScrollPane
 590  * Method:    initIDs
 591  * Signature: ()V
 592  */
 593 JNIEXPORT void JNICALL
 594 Java_java_awt_ScrollPane_initIDs(JNIEnv *env, jclass cls)
 595 {
 596     TRY;
 597 
 598     AwtScrollPane::scrollbarDisplayPolicyID =
 599         env->GetFieldID(cls, "scrollbarDisplayPolicy", "I");
 600     DASSERT(AwtScrollPane::scrollbarDisplayPolicyID != NULL);
 601     CHECK_NULL(AwtScrollPane::scrollbarDisplayPolicyID);
 602 
 603     AwtScrollPane::hAdjustableID =
 604         env->GetFieldID(cls, "hAdjustable", "Ljava/awt/ScrollPaneAdjustable;");
 605     DASSERT(AwtScrollPane::hAdjustableID != NULL);
 606     CHECK_NULL(AwtScrollPane::hAdjustableID);
 607 
 608     AwtScrollPane::vAdjustableID =
 609         env->GetFieldID(cls, "vAdjustable", "Ljava/awt/ScrollPaneAdjustable;");
 610     DASSERT(AwtScrollPane::vAdjustableID != NULL);
 611 
 612     CATCH_BAD_ALLOC;
 613 }
 614 
 615 } /* extern "C" */
 616 
 617 
 618 /************************************************************************
 619  * ScrollPaneAdjustable native methods
 620  */
 621 
 622 extern "C" {
 623 
 624 /*
 625  * Class:     java_awt_ScrollPaneAdjustable
 626  * Method:    initIDs
 627  * Signature: ()V
 628  */
 629 JNIEXPORT void JNICALL
 630 Java_java_awt_ScrollPaneAdjustable_initIDs(JNIEnv *env, jclass cls)
 631 {
 632     TRY;
 633 
 634     AwtScrollPane::unitIncrementID = env->GetFieldID(cls,"unitIncrement", "I");
 635     DASSERT(AwtScrollPane::unitIncrementID != NULL);
 636     CHECK_NULL(AwtScrollPane::unitIncrementID);
 637 
 638     AwtScrollPane::blockIncrementID =
 639         env->GetFieldID(cls,"blockIncrement", "I");
 640     DASSERT(AwtScrollPane::blockIncrementID != NULL);
 641 
 642     CATCH_BAD_ALLOC;
 643 }
 644 
 645 } /* extern "C" */
 646 
 647 
 648 /************************************************************************
 649  * ScrollPanePeer native methods
 650  */
 651 
 652 extern "C" {
 653 
 654 JNIEXPORT void JNICALL
 655 Java_sun_awt_windows_WScrollPanePeer_initIDs(JNIEnv *env, jclass cls)
 656 {
 657     TRY;
 658 
 659     AwtScrollPane::postScrollEventID =
 660         env->GetMethodID(cls, "postScrollEvent", "(IIIZ)V");
 661     DASSERT(AwtScrollPane::postScrollEventID != NULL);
 662 
 663     CATCH_BAD_ALLOC;
 664 }
 665 
 666 /*
 667  * Class:     sun_awt_windows_WScrollPanePeer
 668  * Method:    create
 669  * Signature: (Lsun/awt/windows/WComponentPeer;)V
 670  */
 671 JNIEXPORT void JNICALL
 672 Java_sun_awt_windows_WScrollPanePeer_create(JNIEnv *env, jobject self,
 673                                             jobject parent)
 674 {
 675     TRY;
 676 
 677     DTRACE_PRINTLN2("%x: WScrollPanePeer.create(%x)", self, parent);
 678 
 679     AwtToolkit::CreateComponent(self, parent,
 680                                 (AwtToolkit::ComponentFactory)
 681                                 AwtScrollPane::Create);
 682     PDATA pData;
 683     JNI_CHECK_PEER_CREATION_RETURN(self);
 684     ((AwtScrollPane*)pData)->VerifyState();
 685 
 686     CATCH_BAD_ALLOC;
 687 }
 688 
 689 /*
 690  * Class:     sun_awt_windows_WScrollPanePeer
 691  * Method:    getOffset
 692  * Signature: (I)I
 693  */
 694 JNIEXPORT jint JNICALL
 695 Java_sun_awt_windows_WScrollPanePeer_getOffset(JNIEnv *env, jobject self,
 696                                                jint orient)
 697 {
 698     TRY;
 699 
 700     GetOffsetStruct *gos = new GetOffsetStruct;
 701     gos->scrollpane = env->NewGlobalRef(self);
 702     gos->orient = orient;
 703 
 704     return static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().SyncCall(
 705         (void *(*)(void *))AwtScrollPane::_GetOffset, gos)));
 706     // global ref and gos are deleted in _GetOffset()
 707 
 708     CATCH_BAD_ALLOC_RET(0);
 709 }
 710 
 711 /*
 712  * Class:     sun_awt_windows_WScrollPanePeer
 713  * Method:    setInsets
 714  * Signature: ()V
 715  */
 716 JNIEXPORT void JNICALL
 717 Java_sun_awt_windows_WScrollPanePeer_setInsets(JNIEnv *env, jobject self)
 718 {
 719     TRY
 720 
 721     AwtToolkit::GetInstance().SyncCall(AwtScrollPane::_SetInsets,
 722         env->NewGlobalRef(self));
 723     // global ref is deleted in _SetInsets()
 724 
 725     CATCH_BAD_ALLOC;
 726 }
 727 
 728 /*
 729  * Class:     sun_awt_windows_WScrollPanePeer
 730  * Method:    setScrollPosition
 731  * Signature: (II)V
 732  */
 733 JNIEXPORT void JNICALL
 734 Java_sun_awt_windows_WScrollPanePeer_setScrollPosition(JNIEnv *env,
 735                                                        jobject self,
 736                                                        jint x, jint y)
 737 {
 738     TRY;
 739 
 740     SetScrollPosStruct *ssps = new SetScrollPosStruct;
 741     ssps->scrollpane = env->NewGlobalRef(self);
 742     ssps->x = x;
 743     ssps->y = y;
 744 
 745     AwtToolkit::GetInstance().SyncCall(AwtScrollPane::_SetScrollPos, ssps);
 746     // global ref and ssps are deleted in _SetScrollPos()
 747 
 748     CATCH_BAD_ALLOC;
 749 }
 750 
 751 /*
 752  * Class:     sun_awt_windows_WScrollPanePeer
 753  * Method:    _getHScrollbarHeight
 754  * Signature: ()I
 755  */
 756 JNIEXPORT jint JNICALL
 757 Java_sun_awt_windows_WScrollPanePeer__1getHScrollbarHeight(JNIEnv *env,
 758                                                            jobject self)
 759 {
 760     TRY;
 761 
 762     DTRACE_PRINTLN1("%x: WScrollPanePeer._getHScrollbarHeight()", self);
 763     return ::GetSystemMetrics(SM_CYHSCROLL);
 764 
 765     CATCH_BAD_ALLOC_RET(0);
 766 }
 767 
 768 /*
 769  * Class:     sun_awt_windows_WScrollPanePeer
 770  * Method:    _getVScrollbarWidth
 771  * Signature: ()I
 772  */
 773 JNIEXPORT jint JNICALL
 774 Java_sun_awt_windows_WScrollPanePeer__1getVScrollbarWidth(JNIEnv *env,
 775                                                           jobject self)
 776 {
 777     TRY;
 778 
 779     DTRACE_PRINTLN1("%x: WScrollPanePeer._getVScrollbarHeight()", self);
 780     return ::GetSystemMetrics(SM_CXVSCROLL);
 781 
 782     CATCH_BAD_ALLOC_RET(0);
 783 }
 784 
 785 /*
 786  * Class:     sun_awt_windows_WScrollPanePeer
 787  * Method:    setSpans
 788  * Signature: (IIII)V
 789  */
 790 JNIEXPORT void JNICALL
 791 Java_sun_awt_windows_WScrollPanePeer_setSpans(JNIEnv *env, jobject self,
 792                                               jint parentWidth,
 793                                               jint parentHeight,
 794                                               jint childWidth,
 795                                               jint childHeight)
 796 {
 797     TRY;
 798 
 799     SetSpansStruct *sss = new SetSpansStruct;
 800     sss->scrollpane = env->NewGlobalRef(self);
 801     sss->parentWidth = parentWidth;
 802     sss->parentHeight = parentHeight;
 803     sss->childWidth = childWidth;
 804     sss->childHeight = childHeight;
 805 
 806     AwtToolkit::GetInstance().SyncCall(AwtScrollPane::_SetSpans, sss);
 807     // global ref and sss are deleted in _SetSpans
 808 
 809     CATCH_BAD_ALLOC;
 810 }
 811 
 812 } /* extern "C" */