2 * Copyright 2008-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * John Scipione, jscipione@gmail.com
7 * Clemens Zeidler, haiku@Clemens-Zeidler.de
11 #include "TouchpadPrefView.h"
19 #include <ControlLook.h>
21 #include <FindDirectory.h>
23 #include <LayoutBuilder.h>
25 #include <MenuField.h>
30 #include <SpaceLayoutItem.h>
33 #include <keyboard_mouse_driver.h>
36 const uint32 SCROLL_X_DRAG
= 'sxdr';
37 const uint32 SCROLL_Y_DRAG
= 'sydr';
39 #undef B_TRANSLATION_CONTEXT
40 #define B_TRANSLATION_CONTEXT "TouchpadPrefView"
43 TouchpadView::TouchpadView(BRect frame
)
45 BView(frame
, "TouchpadView", B_FOLLOW_NONE
, B_WILL_DRAW
)
49 fOffScreenView
= NULL
;
50 fOffScreenBitmap
= NULL
;
54 fPadRect
.InsetBy(10, 10);
55 fXScrollRange
= fPadRect
.Width();
56 fYScrollRange
= fPadRect
.Height();
61 TouchpadView::~TouchpadView()
64 delete fOffScreenBitmap
;
69 TouchpadView::Draw(BRect updateRect
)
76 TouchpadView::MouseDown(BPoint point
)
78 if (fXScrollDragZone
.Contains(point
)) {
80 fOldXScrollRange
= fXScrollRange
;
81 SetMouseEventMask(B_POINTER_EVENTS
, B_LOCK_WINDOW_FOCUS
);
84 if (fYScrollDragZone
.Contains(point
)) {
86 fOldYScrollRange
= fYScrollRange
;
87 SetMouseEventMask(B_POINTER_EVENTS
, B_LOCK_WINDOW_FOCUS
);
93 TouchpadView::MouseUp(BPoint point
)
95 if (!fXTracking
&& !fYTracking
)
101 const float kSoftScrollLimit
= 0.7;
104 if (GetRightScrollRatio() > kSoftScrollLimit
105 || GetBottomScrollRatio() > kSoftScrollLimit
) {
106 BAlert
* alert
= new BAlert(B_TRANSLATE("Please confirm"),
107 B_TRANSLATE("The new scroll area is very large and may impede "
108 "normal mouse operation. Do you really want to change it?"),
109 B_TRANSLATE("OK"), B_TRANSLATE("Cancel"),
110 NULL
, B_WIDTH_AS_USUAL
, B_WARNING_ALERT
);
111 alert
->SetShortcut(1, B_ESCAPE
);
112 result
= alert
->Go();
116 BMessage
msg(SCROLL_AREA_CHANGED
);
119 if (GetRightScrollRatio() > kSoftScrollLimit
)
120 fXScrollRange
= fOldXScrollRange
;
121 if (GetBottomScrollRatio() > kSoftScrollLimit
)
122 fYScrollRange
= fOldYScrollRange
;
129 TouchpadView::AttachedToWindow()
132 fOffScreenView
= new BView(Bounds(), "", B_FOLLOW_ALL
, B_WILL_DRAW
);
134 if (!fOffScreenBitmap
) {
135 fOffScreenBitmap
= new BBitmap(Bounds(), B_CMAP8
, true, false);
137 if (fOffScreenBitmap
&& fOffScreenView
)
138 fOffScreenBitmap
->AddChild(fOffScreenView
);
144 TouchpadView::SetValues(float rightRange
, float bottomRange
)
146 fXScrollRange
= fPadRect
.Width() * (1 - rightRange
);
147 fYScrollRange
= fPadRect
.Height() * (1 - bottomRange
);
153 TouchpadView::GetPreferredSize(float* width
, float* height
)
156 *width
= fPrefRect
.Width();
158 *height
= fPrefRect
.Height();
163 TouchpadView::MouseMoved(BPoint point
, uint32 transit
, const BMessage
* message
)
166 if (point
.x
> fPadRect
.right
)
167 fXScrollRange
= fPadRect
.Width();
168 else if (point
.x
< fPadRect
.left
)
171 fXScrollRange
= point
.x
- fPadRect
.left
;
177 if (point
.y
> fPadRect
.bottom
)
178 fYScrollRange
= fPadRect
.Height();
179 else if (point
.y
< fPadRect
.top
)
182 fYScrollRange
= point
.y
- fPadRect
.top
;
191 TouchpadView::DrawSliders()
193 BView
* view
= fOffScreenView
!= NULL
? fOffScreenView
: this;
198 if (fOffScreenBitmap
->Lock()) {
199 view
->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
200 view
->FillRect(Bounds());
201 view
->SetHighColor(100, 100, 100);
202 view
->FillRoundRect(fPadRect
, 4, 4);
204 int32 dragSize
= 3; // half drag size
207 view
->SetHighColor(145, 100, 100);
208 BRect
rightRect(fPadRect
.left
+ fXScrollRange
, fPadRect
.top
,
209 fPadRect
.right
, fPadRect
.bottom
);
210 view
->FillRoundRect(rightRect
, 4, 4);
212 BRect
bottomRect(fPadRect
.left
, fPadRect
.top
+ fYScrollRange
,
213 fPadRect
.right
, fPadRect
.bottom
);
214 view
->FillRoundRect(bottomRect
, 4, 4);
217 view
->SetHighColor(100, 100, 100);
219 view
->StrokeRoundRect(fPadRect
, 4, 4);
221 // x scroll range line
222 view
->SetHighColor(200, 0, 0);
223 view
->StrokeLine(BPoint(fPadRect
.left
+ fXScrollRange
, fPadRect
.top
),
224 BPoint(fPadRect
.left
+ fXScrollRange
, fPadRect
.bottom
));
226 fXScrollDragZone
= BRect(fPadRect
.left
+ fXScrollRange
- dragSize
,
227 fPadRect
.top
- dragSize
, fPadRect
.left
+ fXScrollRange
+ dragSize
,
228 fPadRect
.bottom
+ dragSize
);
229 fXScrollDragZone1
= BRect(fPadRect
.left
+ fXScrollRange
- dragSize
,
230 fPadRect
.top
- dragSize
, fPadRect
.left
+ fXScrollRange
+ dragSize
,
231 fPadRect
.top
+ dragSize
);
232 view
->FillRect(fXScrollDragZone1
);
233 fXScrollDragZone2
= BRect(fPadRect
.left
+ fXScrollRange
- dragSize
,
234 fPadRect
.bottom
- dragSize
,
235 fPadRect
.left
+ fXScrollRange
+ dragSize
,
236 fPadRect
.bottom
+ dragSize
);
237 view
->FillRect(fXScrollDragZone2
);
239 // y scroll range line
240 view
->StrokeLine(BPoint(fPadRect
.left
, fPadRect
.top
+ fYScrollRange
),
241 BPoint(fPadRect
.right
, fPadRect
.top
+ fYScrollRange
));
243 fYScrollDragZone
= BRect(fPadRect
.left
- dragSize
,
244 fPadRect
.top
+ fYScrollRange
- dragSize
,
245 fPadRect
.right
+ dragSize
,
246 fPadRect
.top
+ fYScrollRange
+ dragSize
);
247 fYScrollDragZone1
= BRect(fPadRect
.left
- dragSize
,
248 fPadRect
.top
+ fYScrollRange
- dragSize
, fPadRect
.left
+ dragSize
,
249 fPadRect
.top
+ fYScrollRange
+ dragSize
);
250 view
->FillRect(fYScrollDragZone1
);
251 fYScrollDragZone2
= BRect(fPadRect
.right
- dragSize
,
252 fPadRect
.top
+ fYScrollRange
- dragSize
, fPadRect
.right
+ dragSize
,
253 fPadRect
.top
+ fYScrollRange
+ dragSize
);
254 view
->FillRect(fYScrollDragZone2
);
257 fOffScreenBitmap
->Unlock();
258 DrawBitmap(fOffScreenBitmap
, B_ORIGIN
);
265 // #pragma mark - TouchpadPrefView
268 TouchpadPrefView::TouchpadPrefView()
274 SetValues(&fTouchpadPref
.Settings());
278 TouchpadPrefView::~TouchpadPrefView()
284 TouchpadPrefView::MessageReceived(BMessage
* message
)
286 touchpad_settings
& settings
= fTouchpadPref
.Settings();
288 switch (message
->what
) {
289 case SCROLL_AREA_CHANGED
:
290 settings
.scroll_rightrange
= fTouchpadView
->GetRightScrollRatio();
291 settings
.scroll_bottomrange
= fTouchpadView
->GetBottomScrollRatio();
292 fRevertButton
->SetEnabled(true);
293 fTouchpadPref
.UpdateSettings();
296 case SCROLL_CONTROL_CHANGED
:
297 settings
.scroll_twofinger
= fTwoFingerBox
->Value() == B_CONTROL_ON
;
298 settings
.scroll_twofinger_horizontal
299 = fTwoFingerHorizontalBox
->Value() == B_CONTROL_ON
;
300 settings
.scroll_acceleration
= fScrollAccelSlider
->Value();
301 settings
.scroll_xstepsize
= (20 - fScrollStepXSlider
->Value()) * 3;
302 settings
.scroll_ystepsize
= (20 - fScrollStepYSlider
->Value()) * 3;
303 fRevertButton
->SetEnabled(true);
304 fTwoFingerHorizontalBox
->SetEnabled(settings
.scroll_twofinger
);
305 fTouchpadPref
.UpdateSettings();
308 case TAP_CONTROL_CHANGED
:
309 settings
.tapgesture_sensibility
= fTapSlider
->Value();
310 fRevertButton
->SetEnabled(true);
311 fTouchpadPref
.UpdateSettings();
314 case DEFAULT_SETTINGS
:
315 fTouchpadPref
.Defaults();
316 fRevertButton
->SetEnabled(true);
317 fTouchpadPref
.UpdateSettings();
318 SetValues(&settings
);
321 case REVERT_SETTINGS
:
322 fTouchpadPref
.Revert();
323 fTouchpadPref
.UpdateSettings();
324 fRevertButton
->SetEnabled(false);
325 SetValues(&settings
);
329 BView::MessageReceived(message
);
335 TouchpadPrefView::AttachedToWindow()
337 fTouchpadView
->SetTarget(this);
338 fTwoFingerBox
->SetTarget(this);
339 fTwoFingerHorizontalBox
->SetTarget(this);
340 fScrollStepXSlider
->SetTarget(this);
341 fScrollStepYSlider
->SetTarget(this);
342 fScrollAccelSlider
->SetTarget(this);
343 fTapSlider
->SetTarget(this);
344 fDefaultButton
->SetTarget(this);
345 fRevertButton
->SetTarget(this);
346 BSize size
= PreferredSize();
347 Window()->ResizeTo(size
.width
, size
.height
);
349 BPoint position
= fTouchpadPref
.WindowPosition();
350 // center window on screen if it had a bad position
351 if (position
.x
< 0 && position
.y
< 0)
352 Window()->CenterOnScreen();
354 Window()->MoveTo(position
);
359 TouchpadPrefView::DetachedFromWindow()
361 fTouchpadPref
.SetWindowPosition(Window()->Frame().LeftTop());
366 TouchpadPrefView::SetupView()
368 SetLayout(new BGroupLayout(B_VERTICAL
));
369 BBox
* scrollBox
= new BBox("Touchpad");
370 scrollBox
->SetLabel(B_TRANSLATE("Scrolling"));
372 fTouchpadView
= new TouchpadView(BRect(0, 0, 130, 120));
373 fTouchpadView
->SetExplicitMaxSize(BSize(130, 120));
375 // Create the "Mouse Speed" slider...
376 fScrollAccelSlider
= new BSlider("scroll_accel",
377 B_TRANSLATE("Acceleration"),
378 new BMessage(SCROLL_CONTROL_CHANGED
), 0, 20, B_HORIZONTAL
);
379 fScrollAccelSlider
->SetHashMarks(B_HASH_MARKS_BOTTOM
);
380 fScrollAccelSlider
->SetHashMarkCount(7);
381 fScrollAccelSlider
->SetLimitLabels(B_TRANSLATE("Slow"),
382 B_TRANSLATE("Fast"));
383 fScrollAccelSlider
->SetExplicitMinSize(BSize(150, B_SIZE_UNSET
));
385 fScrollStepXSlider
= new BSlider("scroll_stepX",
386 B_TRANSLATE("Horizontal"),
387 new BMessage(SCROLL_CONTROL_CHANGED
),
388 0, 20, B_HORIZONTAL
);
389 fScrollStepXSlider
->SetHashMarks(B_HASH_MARKS_BOTTOM
);
390 fScrollStepXSlider
->SetHashMarkCount(7);
391 fScrollStepXSlider
->SetLimitLabels(B_TRANSLATE("Slow"),
392 B_TRANSLATE("Fast"));
394 fScrollStepYSlider
= new BSlider("scroll_stepY",
395 B_TRANSLATE("Vertical"),
396 new BMessage(SCROLL_CONTROL_CHANGED
), 0, 20, B_HORIZONTAL
);
397 fScrollStepYSlider
->SetHashMarks(B_HASH_MARKS_BOTTOM
);
398 fScrollStepYSlider
->SetHashMarkCount(7);
399 fScrollStepYSlider
->SetLimitLabels(B_TRANSLATE("Slow"),
400 B_TRANSLATE("Fast"));
402 fTwoFingerBox
= new BCheckBox(B_TRANSLATE("Two finger scrolling"),
403 new BMessage(SCROLL_CONTROL_CHANGED
));
404 fTwoFingerHorizontalBox
= new BCheckBox(
405 B_TRANSLATE("Horizontal scrolling"),
406 new BMessage(SCROLL_CONTROL_CHANGED
));
408 float spacing
= be_control_look
->DefaultItemSpacing();
410 BView
* scrollPrefLeftLayout
411 = BLayoutBuilder::Group
<>(B_VERTICAL
, 0)
415 .AddGroup(B_HORIZONTAL
, 0)
416 .AddStrut(spacing
* 2)
417 .Add(fTwoFingerHorizontalBox
)
422 BGroupView
* scrollPrefRightLayout
= new BGroupView(B_VERTICAL
);
423 scrollPrefRightLayout
->AddChild(fScrollAccelSlider
);
424 scrollPrefRightLayout
->AddChild(fScrollStepXSlider
);
425 scrollPrefRightLayout
->AddChild(fScrollStepYSlider
);
427 BGroupLayout
* scrollPrefLayout
= new BGroupLayout(B_HORIZONTAL
);
428 scrollPrefLayout
->SetSpacing(spacing
);
429 scrollPrefLayout
->SetInsets(spacing
,
430 scrollBox
->TopBorderOffset() * 2 + spacing
, spacing
, spacing
);
431 scrollBox
->SetLayout(scrollPrefLayout
);
433 scrollPrefLayout
->AddView(scrollPrefLeftLayout
);
434 scrollPrefLayout
->AddItem(BSpaceLayoutItem::CreateVerticalStrut(spacing
436 scrollPrefLayout
->AddView(scrollPrefRightLayout
);
438 BBox
* tapBox
= new BBox("tapbox");
439 tapBox
->SetLabel(B_TRANSLATE("Tapping"));
441 BGroupLayout
* tapPrefLayout
= new BGroupLayout(B_HORIZONTAL
);
442 tapPrefLayout
->SetInsets(spacing
, tapBox
->TopBorderOffset() * 2 + spacing
,
444 tapBox
->SetLayout(tapPrefLayout
);
446 fTapSlider
= new BSlider("tap_sens", B_TRANSLATE("Sensitivity"),
447 new BMessage(TAP_CONTROL_CHANGED
), 0, spacing
* 2, B_HORIZONTAL
);
448 fTapSlider
->SetHashMarks(B_HASH_MARKS_BOTTOM
);
449 fTapSlider
->SetHashMarkCount(7);
450 fTapSlider
->SetLimitLabels(B_TRANSLATE("Off"), B_TRANSLATE("High"));
452 tapPrefLayout
->AddView(fTapSlider
);
454 fDefaultButton
= new BButton(B_TRANSLATE("Defaults"),
455 new BMessage(DEFAULT_SETTINGS
));
457 fRevertButton
= new BButton(B_TRANSLATE("Revert"),
458 new BMessage(REVERT_SETTINGS
));
459 fRevertButton
->SetEnabled(false);
461 BLayoutBuilder::Group
<>(this, B_VERTICAL
)
462 .SetInsets(B_USE_DEFAULT_SPACING
)
465 .AddGroup(B_HORIZONTAL
)
475 TouchpadPrefView::SetValues(touchpad_settings
* settings
)
477 fTouchpadView
->SetValues(settings
->scroll_rightrange
,
478 settings
->scroll_bottomrange
);
479 fTwoFingerBox
->SetValue(settings
->scroll_twofinger
480 ? B_CONTROL_ON
: B_CONTROL_OFF
);
481 fTwoFingerHorizontalBox
->SetValue(settings
->scroll_twofinger_horizontal
482 ? B_CONTROL_ON
: B_CONTROL_OFF
);
483 fTwoFingerHorizontalBox
->SetEnabled(settings
->scroll_twofinger
);
484 fScrollStepXSlider
->SetValue(20 - settings
->scroll_xstepsize
/ 2);
485 fScrollStepYSlider
->SetValue(20 - settings
->scroll_ystepsize
/ 2);
486 fScrollAccelSlider
->SetValue(settings
->scroll_acceleration
);
487 fTapSlider
->SetValue(settings
->tapgesture_sensibility
);