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