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_Toolkit.h"
27 #include "awt_Scrollbar.h"
28 #include "awt_Canvas.h"
29 #include "awt_Window.h"
30 
31 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
32  */
33 
34 /***********************************************************************/
35 // struct for _SetValues() method
36 struct SetValuesStruct {
37     jobject scrollbar;
38     jint value;
39     jint visible;
40     jint min, max;
41 };
42 // struct for _SetLineIncrement()/_SetPageIncrement() methods
43 struct SetIncrementStruct {
44     jobject scrollbar;
45     jint increment;
46 };
47 /************************************************************************
48  * AwtScrollbar fields
49  */
50 
51 jfieldID AwtScrollbar::lineIncrementID;
52 jfieldID AwtScrollbar::pageIncrementID;
53 jfieldID AwtScrollbar::orientationID;
54 
55 BOOL     AwtScrollbar::ms_isInsideMouseFilter = FALSE;
56 int      AwtScrollbar::ms_instanceCounter = 0;
57 HHOOK    AwtScrollbar::ms_hMouseFilter;
58 
59 /************************************************************************
60  * AwtScrollbar methods
61  */
62 
AwtScrollbar()63 AwtScrollbar::AwtScrollbar() {
64     m_orientation = SB_HORZ;
65     m_lineIncr = 0;
66     m_pageIncr = 0;
67     m_prevCallback = NULL;
68     m_prevCallbackPos = 0;
69     ms_instanceCounter++;
70 
71     /*
72      * Fix for 4515085.
73      * Use the hook to process WM_LBUTTONUP message.
74      */
75     if (AwtScrollbar::ms_instanceCounter == 1) {
76         AwtScrollbar::ms_hMouseFilter =
77             ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)AwtScrollbar::MouseFilter,
78                                0, AwtToolkit::MainThread());
79     }
80 }
81 
~AwtScrollbar()82 AwtScrollbar::~AwtScrollbar()
83 {
84 }
85 
Dispose()86 void AwtScrollbar::Dispose()
87 {
88     if (--ms_instanceCounter == 0) {
89         ::UnhookWindowsHookEx(ms_hMouseFilter);
90     }
91     AwtComponent::Dispose();
92 }
93 
94 LPCTSTR
GetClassName()95 AwtScrollbar::GetClassName() {
96     return TEXT("SCROLLBAR");  /* System provided scrollbar class */
97 }
98 
99 /* Create a new AwtScrollbar object and window.   */
100 AwtScrollbar *
Create(jobject peer,jobject parent)101 AwtScrollbar::Create(jobject peer, jobject parent)
102 {
103     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
104 
105     jobject target = NULL;
106     AwtScrollbar* c = NULL;
107 
108     try {
109         if (env->EnsureLocalCapacity(1) < 0) {
110             return NULL;
111         }
112 
113         PDATA pData;
114         AwtCanvas* awtParent;
115 
116         JNI_CHECK_PEER_GOTO(parent, done);
117         awtParent = (AwtCanvas*)pData;
118 
119         target = env->GetObjectField(peer, AwtObject::targetID);
120         JNI_CHECK_NULL_GOTO(target, "null target", done);
121 
122         c = new AwtScrollbar();
123 
124         {
125             jint orientation =
126                 env->GetIntField(target, AwtScrollbar::orientationID);
127             c->m_orientation = (orientation == java_awt_Scrollbar_VERTICAL) ?
128                 SB_VERT : SB_HORZ;
129             c->m_lineIncr =
130                 env->GetIntField(target, AwtScrollbar::lineIncrementID);
131             c->m_pageIncr =
132                 env->GetIntField(target, AwtScrollbar::pageIncrementID);
133 
134             DWORD style = WS_CHILD | WS_CLIPSIBLINGS |
135                 c->m_orientation;/* Note: SB_ and SBS_ are the same here */
136 
137             jint x = env->GetIntField(target, AwtComponent::xID);
138             jint y = env->GetIntField(target, AwtComponent::yID);
139             jint width = env->GetIntField(target, AwtComponent::widthID);
140             jint height = env->GetIntField(target, AwtComponent::heightID);
141 
142             c->CreateHWnd(env, L"", style, 0,
143                           x, y, width, height,
144                           awtParent->GetHWnd(),
145                           reinterpret_cast<HMENU>(static_cast<INT_PTR>(
146                 awtParent->CreateControlID())),
147                           ::GetSysColor(COLOR_SCROLLBAR),
148                           ::GetSysColor(COLOR_SCROLLBAR),
149                           peer);
150             c->m_backgroundColorSet = TRUE;
151             /* suppress inheriting parent's color. */
152             c->UpdateBackground(env, target);
153         }
154     } catch (...) {
155         env->DeleteLocalRef(target);
156         throw;
157     }
158 
159 done:
160     env->DeleteLocalRef(target);
161     return c;
162 }
163 
164 LRESULT CALLBACK
MouseFilter(int nCode,WPARAM wParam,LPARAM lParam)165 AwtScrollbar::MouseFilter(int nCode, WPARAM wParam, LPARAM lParam)
166 {
167     if (((UINT)wParam == WM_LBUTTONUP || (UINT)wParam == WM_MOUSEMOVE) &&
168         ms_isInsideMouseFilter != TRUE &&
169         nCode >= 0)
170     {
171         HWND hwnd = ((PMOUSEHOOKSTRUCT)lParam)->hwnd;
172         AwtComponent *comp = AwtComponent::GetComponent(hwnd);
173 
174         if (comp != NULL && comp->IsScrollbar()) {
175             MSG msg;
176             LPMSG lpMsg = (LPMSG)&msg;
177             UINT msgID = (UINT)wParam;
178 
179             ms_isInsideMouseFilter = TRUE;
180 
181             // Peek the message to get wParam containing the message's flags.
182             // <::PeekMessage> will call this hook again. To prevent recursive
183             // processing the <ms_isInsideMouseFilter> flag is used.
184             // Calling <::PeekMessage> is not so good desision but is the only one
185             // found to get those flags (used further in Java event creation).
186             // WARNING! If you are about to add new hook of WM_MOUSE type make
187             // it ready for recursive call, otherwise modify this one.
188             if (::PeekMessage(lpMsg, hwnd, msgID, msgID, PM_NOREMOVE)) {
189                 comp->WindowProc(msgID, lpMsg->wParam, lpMsg->lParam);
190             }
191 
192             ms_isInsideMouseFilter = FALSE;
193         }
194     }
195     return ::CallNextHookEx(AwtScrollbar::ms_hMouseFilter, nCode, wParam, lParam);
196 }
197 
198 
199 LRESULT
WindowProc(UINT message,WPARAM wParam,LPARAM lParam)200 AwtScrollbar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
201 {
202     // Delegate real work to super
203     LRESULT retValue = AwtComponent::WindowProc(message, wParam, lParam);
204 
205     // After-hooks for workarounds
206     switch (message) {
207 
208       // Work around a windows bug described in KB article Q73839.
209       // Need to update focus indicator on scrollbar if thumb
210       // proportion or thumb position was changed.
211 
212       case WM_SIZE:
213       case SBM_SETSCROLLINFO:
214       case SBM_SETRANGE:
215       case SBM_SETRANGEREDRAW:
216           if (AwtComponent::sm_focusOwner == GetHWnd()) {
217               UpdateFocusIndicator();
218           }
219           break;
220     }
221 
222     return retValue;
223 }
224 
225 MsgRouting
WmNcHitTest(UINT x,UINT y,LRESULT & retVal)226 AwtScrollbar::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
227 {
228     if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) {
229         retVal = HTCLIENT;
230         return mrConsume;
231     }
232     return AwtComponent::WmNcHitTest(x, y, retVal);
233 }
234 
235 // Fix for a race condition when the WM_LBUTTONUP is picked by the AWT
236 // message loop before(!) the windows internal message loop for the
237 // scrollbar is started in response to WM_LBUTTONDOWN.  See KB article
238 // Q102552.
239 //
240 // Note that WM_LBUTTONUP is processed by the windows internal message
241 // loop.  May be we can synthesize a MOUSE_RELEASED event but that
242 // seems kludgey, so we'd better left this as is for now.
243 
244 MsgRouting
WmMouseDown(UINT flags,int x,int y,int button)245 AwtScrollbar::WmMouseDown(UINT flags, int x, int y, int button)
246 {
247     // We pass the WM_LBUTTONDOWN up to Java, but we process it
248     // immediately as well to avoid the race.  Later when this press
249     // event returns to us wrapped into a WM_AWT_HANDLE_EVENT we
250     // ignore it in the HandleEvent below.  This means that we can not
251     // consume the mouse press in the Java world.
252 
253     MsgRouting usualRoute = AwtComponent::WmMouseDown(flags, x, y, button);
254 
255     if (::IsWindow(AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(GetHWnd())))) {
256         return mrConsume;
257     }
258 
259     if (button == LEFT_BUTTON)
260         return mrDoDefault;    // Force immediate processing to avoid the race.
261     else
262         return usualRoute;
263 }
264 
265 MsgRouting
HandleEvent(MSG * msg,BOOL synthetic)266 AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic)
267 {
268     // SCROLLBAR control doesn't cause activation on mouse/key events,
269     // so we can safely (for synthetic focus) pass them to the system proc.
270 
271     if (IsFocusingMouseMessage(msg)) {
272         // Left button press was already routed to default window
273         // procedure in the WmMouseDown above.  Propagating synthetic
274         // press seems like a bad idea as internal message loop
275         // doesn't know how to unwrap synthetic release.
276         delete msg;
277         return mrConsume;
278     }
279     return AwtComponent::HandleEvent(msg, synthetic);
280 }
281 
282 // Work around a windows bug descrbed in KB article Q73839.  Reset
283 // focus on scrollbars to update focus indicator.  The article advises
284 // to disable/enable the scrollbar.
285 void
UpdateFocusIndicator()286 AwtScrollbar::UpdateFocusIndicator()
287 {
288     if (IsFocusable()) {
289         // todo: doesn't work
290         SendMessage((WPARAM)ESB_DISABLE_BOTH);
291         SendMessage((WPARAM)ESB_ENABLE_BOTH);
292     }
293 }
294 
295 // In a windows app one would call SetScrollInfo from WM_[HV]SCROLL
296 // handler directly.  Since we call SetScrollInfo from Java world
297 // after scroll handler is over next WM_[HV]SCROLL event can be
298 // delivered before SetScrollInfo was called in response to the
299 // previous one and thus we would fire exactly the same event which
300 // will only contribute to the growth of the backlog of scroll events.
301 
302 const char * const AwtScrollbar::SbNlineDown = "lineDown";
303 const char * const AwtScrollbar::SbNlineUp   = "lineUp";
304 const char * const AwtScrollbar::SbNpageDown = "pageDown";
305 const char * const AwtScrollbar::SbNpageUp   = "pageUp";
306 const char * const AwtScrollbar::SbNdrag     = "drag";
307 const char * const AwtScrollbar::SbNdragEnd  = "dragEnd";
308 const char * const AwtScrollbar::SbNwarp     = "warp";
309 
310 inline void
DoScrollCallbackCoalesce(const char * methodName,int newPos)311 AwtScrollbar::DoScrollCallbackCoalesce(const char* methodName, int newPos)
312 {
313     if (methodName == m_prevCallback && newPos == m_prevCallbackPos) {
314         DTRACE_PRINTLN2("AwtScrollbar: ignoring duplicate callback %s(%d)",
315                         methodName, newPos);
316     }
317     else {
318         DoCallback(methodName, "(I)V", newPos);
319         m_prevCallback = methodName;
320         m_prevCallbackPos = newPos;
321     }
322 }
323 
324 
325 MsgRouting
WmVScroll(UINT scrollCode,UINT pos,HWND hScrollbar)326 AwtScrollbar::WmVScroll(UINT scrollCode, UINT pos, HWND hScrollbar)
327 {
328     int minVal, maxVal;    // scrollbar range
329     int minPos, maxPos;    // thumb positions (max depends on visible amount)
330     int curPos, newPos;
331 
332     // For drags we have old (static) and new (dynamic) thumb positions
333     int dragP = (scrollCode == SB_THUMBTRACK
334               || scrollCode == SB_THUMBPOSITION);
335     int thumbPos;
336 
337     SCROLLINFO si;
338     si.cbSize = sizeof si;
339     si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
340 
341     // From, _Win32 Programming_, by Rector and Newcommer, p. 185:
342     // "In some of the older documentation on Win32 scroll bars,
343     // including that published by Microsoft, you may read that
344     // you *cannot* obtain the scroll position while in a handler.
345     // The SIF_TRACKPOS flag was added after this documentation
346     // was published.  Beware of this older documentation; it may
347     // have other obsolete features."
348     if (dragP) {
349         si.fMask |= SIF_TRACKPOS;
350     }
351 
352     VERIFY(::GetScrollInfo(GetHWnd(), SB_CTL, &si));
353     curPos = si.nPos;
354     minPos = minVal = si.nMin;
355 
356     // Upper bound of the range.  Note that adding 1 here is safe
357     // and won't cause a wrap, since we have substracted 1 in the
358     // SetValues above.
359     maxVal = si.nMax + 1;
360 
361     // Meaningful maximum position is maximum - visible.
362     maxPos = maxVal - si.nPage;
363 
364     // XXX: Documentation for SBM_SETRANGE says that scrollbar
365     // range is limited by MAXLONG, which is 2**31, but when a
366     // scroll range is greater than that, thumbPos is reported
367     // incorrectly due to integer arithmetic wrap(s).
368     thumbPos = dragP ? si.nTrackPos : curPos;
369 
370     // NB: Beware arithmetic wrap when calculating newPos
371     switch (scrollCode) {
372 
373       case SB_LINEUP:
374           if ((__int64)curPos - m_lineIncr > minPos)
375               newPos = curPos - m_lineIncr;
376           else
377               newPos = minPos;
378           if (newPos != curPos)
379               DoScrollCallbackCoalesce(SbNlineUp, newPos);
380           break;
381 
382       case SB_LINEDOWN:
383           if ((__int64)curPos + m_lineIncr < maxPos)
384               newPos = curPos + m_lineIncr;
385           else
386               newPos = maxPos;
387           if (newPos != curPos)
388               DoScrollCallbackCoalesce(SbNlineDown, newPos);
389           break;
390 
391       case SB_PAGEUP:
392           if ((__int64)curPos - m_pageIncr > minPos)
393               newPos = curPos - m_pageIncr;
394           else
395               newPos = minPos;
396           if (newPos != curPos)
397               DoScrollCallbackCoalesce(SbNpageUp, newPos);
398           break;
399 
400       case SB_PAGEDOWN:
401           if ((__int64)curPos + m_pageIncr < maxPos)
402               newPos = curPos + m_pageIncr;
403           else
404               newPos = maxPos;
405           if (newPos != curPos)
406               DoScrollCallbackCoalesce(SbNpageDown, newPos);
407           break;
408 
409       case SB_TOP:
410           if (minPos != curPos)
411               DoScrollCallbackCoalesce(SbNwarp, minPos);
412           break;
413 
414       case SB_BOTTOM:
415           if (maxPos != curPos)
416               DoScrollCallbackCoalesce(SbNwarp, maxPos);
417           break;
418 
419       case SB_THUMBTRACK:
420           if (thumbPos != curPos)
421               DoScrollCallbackCoalesce(SbNdrag, thumbPos);
422           break;
423 
424       case SB_THUMBPOSITION:
425           DoScrollCallbackCoalesce(SbNdragEnd, thumbPos);
426           break;
427 
428       case SB_ENDSCROLL:
429           // reset book-keeping info
430           m_prevCallback = NULL;
431           break;
432     }
433     return mrDoDefault;
434 }
435 
436 MsgRouting
WmHScroll(UINT scrollCode,UINT pos,HWND hScrollbar)437 AwtScrollbar::WmHScroll(UINT scrollCode, UINT pos, HWND hScrollbar)
438 {
439     return WmVScroll(scrollCode, pos, hScrollbar);
440 }
441 
_SetValues(void * param)442 void AwtScrollbar::_SetValues(void *param)
443 {
444     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
445 
446     SetValuesStruct *svs = (SetValuesStruct *)param;
447     jobject self = svs->scrollbar;
448 
449     SCROLLINFO si;
450     si.cbSize = sizeof si;
451     si.fMask  = SIF_POS | SIF_PAGE | SIF_RANGE;
452     si.nMin   = svs->min;
453     si.nMax   = svs->max - 1;
454     si.nPage  = svs->visible;
455     si.nPos   = svs->value;
456 
457     AwtScrollbar *sb = NULL;
458 
459     PDATA pData;
460     JNI_CHECK_PEER_GOTO(self, ret);
461     sb = (AwtScrollbar *)pData;
462     if (::IsWindow(sb->GetHWnd()))
463     {
464         BOOL update_p = ::IsWindowEnabled(sb->GetHWnd()); // don't redraw if disabled
465         DTRACE_PRINTLN5("AwtScrollbar::SetValues(val = %d, vis = %d,"//(ctd.)
466                         " min = %d, max = %d)%s",
467             svs->value, svs->visible, svs->min, svs->max,
468             update_p ? "" : " - NOT redrawing");
469         ::SetScrollInfo(sb->GetHWnd(), SB_CTL, &si, update_p);
470     }
471 ret:
472     env->DeleteGlobalRef(self);
473 
474     delete svs;
475 }
476 
_SetLineIncrement(void * param)477 void AwtScrollbar::_SetLineIncrement(void *param)
478 {
479     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
480 
481     SetIncrementStruct *sis = (SetIncrementStruct *)param;
482     jobject self = sis->scrollbar;
483     jint increment = sis->increment;
484 
485     AwtScrollbar *sb = NULL;
486 
487     PDATA pData;
488     JNI_CHECK_PEER_GOTO(self, ret);
489     sb = (AwtScrollbar *)pData;
490     if (::IsWindow(sb->GetHWnd()))
491     {
492         sb->SetLineIncrement(increment);
493     }
494 ret:
495     env->DeleteGlobalRef(self);
496 
497     delete sis;
498 }
499 
_SetPageIncrement(void * param)500 void AwtScrollbar::_SetPageIncrement(void *param)
501 {
502     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
503 
504     SetIncrementStruct *sis = (SetIncrementStruct *)param;
505     jobject self = sis->scrollbar;
506     jint increment = sis->increment;
507 
508     AwtScrollbar *sb = NULL;
509 
510     PDATA pData;
511     JNI_CHECK_PEER_GOTO(self, ret);
512     sb = (AwtScrollbar *)pData;
513     if (::IsWindow(sb->GetHWnd()))
514     {
515         sb->SetPageIncrement(increment);
516     }
517 ret:
518     env->DeleteGlobalRef(self);
519 
520     delete sis;
521 }
522 
523 /************************************************************************
524  * Scrollbar native methods
525  */
526 
527 extern "C" {
528 
529 /*
530  * Class:     java_awt_Scrollbar
531  * Method:    initIDs
532  * Signature: ()V
533  */
534 JNIEXPORT void JNICALL
Java_java_awt_Scrollbar_initIDs(JNIEnv * env,jclass cls)535 Java_java_awt_Scrollbar_initIDs(JNIEnv *env, jclass cls)
536 {
537     TRY;
538 
539     AwtScrollbar::lineIncrementID = env->GetFieldID(cls, "lineIncrement", "I");
540     DASSERT(AwtScrollbar::lineIncrementID != NULL);
541     CHECK_NULL(AwtScrollbar::lineIncrementID);
542 
543     AwtScrollbar::pageIncrementID = env->GetFieldID(cls, "pageIncrement", "I");
544     DASSERT(AwtScrollbar::pageIncrementID != NULL);
545     CHECK_NULL(AwtScrollbar::pageIncrementID);
546 
547     AwtScrollbar::orientationID = env->GetFieldID(cls, "orientation", "I");
548     DASSERT(AwtScrollbar::orientationID != NULL);
549 
550     CATCH_BAD_ALLOC;
551 }
552 
553 } /* extern "C" */
554 
555 
556 /************************************************************************
557  * WScrollbarPeer native methods
558  */
559 
560 extern "C" {
561 
562 /*
563  * Class:     sun_awt_windows_WScrollbarPeer
564  * Method:    setValues
565  * Signature: (IIII)V
566  */
567 JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollbarPeer_setValues(JNIEnv * env,jobject self,jint value,jint visible,jint minimum,jint maximum)568 Java_sun_awt_windows_WScrollbarPeer_setValues(JNIEnv *env, jobject self,
569                                               jint value, jint visible,
570                                               jint minimum, jint maximum)
571 {
572     TRY;
573 
574     SetValuesStruct *svs = new SetValuesStruct;
575     svs->scrollbar = env->NewGlobalRef(self);
576     svs->value = value;
577     svs->visible = visible;
578     svs->min = minimum;
579     svs->max = maximum;
580 
581     AwtToolkit::GetInstance().SyncCall(AwtScrollbar::_SetValues, svs);
582     // global ref and svs are deleted in _SetValues
583 
584     CATCH_BAD_ALLOC;
585 }
586 
587 /*
588  * Class:     sun_awt_windows_WScrollbarPeer
589  * Method:    setLineIncrement
590  * Signature: (I)V
591  */
592 JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollbarPeer_setLineIncrement(JNIEnv * env,jobject self,jint increment)593 Java_sun_awt_windows_WScrollbarPeer_setLineIncrement(JNIEnv *env, jobject self,
594                                                      jint increment)
595 {
596     TRY;
597 
598     SetIncrementStruct *sis = new SetIncrementStruct;
599     sis->scrollbar = env->NewGlobalRef(self);
600     sis->increment = increment;
601 
602     AwtToolkit::GetInstance().SyncCall(AwtScrollbar::_SetLineIncrement, sis);
603     // global ref and svs are deleted in _SetValues
604 
605     CATCH_BAD_ALLOC;
606 }
607 
608 /*
609  * Class:     sun_awt_windows_WScrollbarPeer
610  * Method:    setPageIncrement
611  * Signature: (I)V
612  */
613 JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollbarPeer_setPageIncrement(JNIEnv * env,jobject self,jint increment)614 Java_sun_awt_windows_WScrollbarPeer_setPageIncrement(JNIEnv *env, jobject self,
615                                                      jint increment)
616 {
617     TRY;
618 
619     SetIncrementStruct *sis = new SetIncrementStruct;
620     sis->scrollbar = env->NewGlobalRef(self);
621     sis->increment = increment;
622 
623     AwtToolkit::GetInstance().SyncCall(AwtScrollbar::_SetPageIncrement, sis);
624     // global ref and svs are deleted in _SetValues
625 
626     CATCH_BAD_ALLOC;
627 }
628 
629 /*
630  * Class:     sun_awt_windows_WScrollbarPeer
631  * Method:    create
632  * Signature: (Lsun/awt/windows/WComponentPeer;)V
633  */
634 JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollbarPeer_create(JNIEnv * env,jobject self,jobject parent)635 Java_sun_awt_windows_WScrollbarPeer_create(JNIEnv *env, jobject self,
636                                            jobject parent)
637 {
638     TRY;
639 
640     AwtToolkit::CreateComponent(self, parent,
641                                 (AwtToolkit::ComponentFactory)
642                                 AwtScrollbar::Create);
643 
644     CATCH_BAD_ALLOC;
645 }
646 
647 /*
648  * Class:     sun_awt_windows_WScrollbarPeer
649  * Method:    getScrollbarSize
650  * Signature: (I)I
651  */
652 JNIEXPORT jint JNICALL
Java_sun_awt_windows_WScrollbarPeer_getScrollbarSize(JNIEnv * env,jclass clazz,jint orientation)653 Java_sun_awt_windows_WScrollbarPeer_getScrollbarSize(JNIEnv *env, jclass clazz, jint orientation)
654 {
655     if (orientation == java_awt_Scrollbar_VERTICAL) {
656         return ::GetSystemMetrics(SM_CXVSCROLL);
657     } else {
658         return ::GetSystemMetrics(SM_CYHSCROLL);
659     }
660 }
661 
662 } /* extern "C" */
663