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()
63 delete fOffScreenBitmap
;
68 TouchpadView::Draw(BRect updateRect
)
75 TouchpadView::MouseDown(BPoint point
)
77 if (fXScrollDragZone
.Contains(point
)) {
79 fOldXScrollRange
= fXScrollRange
;
80 SetMouseEventMask(B_POINTER_EVENTS
, B_LOCK_WINDOW_FOCUS
);
83 if (fYScrollDragZone
.Contains(point
)) {
85 fOldYScrollRange
= fYScrollRange
;
86 SetMouseEventMask(B_POINTER_EVENTS
, B_LOCK_WINDOW_FOCUS
);
92 TouchpadView::MouseUp(BPoint point
)
94 if (!fXTracking
&& !fYTracking
)
100 const float kSoftScrollLimit
= 0.7;
103 if (GetRightScrollRatio() > kSoftScrollLimit
104 || GetBottomScrollRatio() > kSoftScrollLimit
) {
105 BAlert
* alert
= new BAlert(B_TRANSLATE("Please confirm"),
106 B_TRANSLATE("The new scroll area is very large and may impede "
107 "normal mouse operation. Do you really want to change it?"),
108 B_TRANSLATE("OK"), B_TRANSLATE("Cancel"),
109 NULL
, B_WIDTH_AS_USUAL
, B_WARNING_ALERT
);
110 alert
->SetShortcut(1, B_ESCAPE
);
111 result
= alert
->Go();
115 BMessage
msg(SCROLL_AREA_CHANGED
);
118 if (GetRightScrollRatio() > kSoftScrollLimit
)
119 fXScrollRange
= fOldXScrollRange
;
120 if (GetBottomScrollRatio() > kSoftScrollLimit
)
121 fYScrollRange
= fOldYScrollRange
;
128 TouchpadView::AttachedToWindow()
131 fOffScreenView
= new BView(Bounds(), "", B_FOLLOW_ALL
, B_WILL_DRAW
);
133 if (!fOffScreenBitmap
) {
134 fOffScreenBitmap
= new BBitmap(Bounds(), B_CMAP8
, true, false);
136 if (fOffScreenBitmap
&& fOffScreenView
)
137 fOffScreenBitmap
->AddChild(fOffScreenView
);
143 TouchpadView::SetValues(float rightRange
, float bottomRange
)
145 fXScrollRange
= fPadRect
.Width() * (1 - rightRange
);
146 fYScrollRange
= fPadRect
.Height() * (1 - bottomRange
);
152 TouchpadView::GetPreferredSize(float* width
, float* height
)
155 *width
= fPrefRect
.Width();
157 *height
= fPrefRect
.Height();
162 TouchpadView::MouseMoved(BPoint point
, uint32 transit
, const BMessage
* message
)
165 if (point
.x
> fPadRect
.right
)
166 fXScrollRange
= fPadRect
.Width();
167 else if (point
.x
< fPadRect
.left
)
170 fXScrollRange
= point
.x
- fPadRect
.left
;
176 if (point
.y
> fPadRect
.bottom
)
177 fYScrollRange
= fPadRect
.Height();
178 else if (point
.y
< fPadRect
.top
)
181 fYScrollRange
= point
.y
- fPadRect
.top
;
190 TouchpadView::DrawSliders()
192 BView
* view
= fOffScreenView
!= NULL
? fOffScreenView
: this;
197 if (fOffScreenBitmap
->Lock()) {
198 view
->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
199 view
->FillRect(Bounds());
200 view
->SetHighColor(100, 100, 100);
201 view
->FillRoundRect(fPadRect
, 4, 4);
203 int32 dragSize
= 3; // half drag size
206 view
->SetHighColor(145, 100, 100);
207 BRect
rightRect(fPadRect
.left
+ fXScrollRange
, fPadRect
.top
,
208 fPadRect
.right
, fPadRect
.bottom
);
209 view
->FillRoundRect(rightRect
, 4, 4);
211 BRect
bottomRect(fPadRect
.left
, fPadRect
.top
+ fYScrollRange
,
212 fPadRect
.right
, fPadRect
.bottom
);
213 view
->FillRoundRect(bottomRect
, 4, 4);
216 view
->SetHighColor(100, 100, 100);
218 view
->StrokeRoundRect(fPadRect
, 4, 4);
220 // x scroll range line
221 view
->SetHighColor(200, 0, 0);
222 view
->StrokeLine(BPoint(fPadRect
.left
+ fXScrollRange
, fPadRect
.top
),
223 BPoint(fPadRect
.left
+ fXScrollRange
, fPadRect
.bottom
));
225 fXScrollDragZone
= BRect(fPadRect
.left
+ fXScrollRange
- dragSize
,
226 fPadRect
.top
- dragSize
, fPadRect
.left
+ fXScrollRange
+ dragSize
,
227 fPadRect
.bottom
+ dragSize
);
228 fXScrollDragZone1
= BRect(fPadRect
.left
+ fXScrollRange
- dragSize
,
229 fPadRect
.top
- dragSize
, fPadRect
.left
+ fXScrollRange
+ dragSize
,
230 fPadRect
.top
+ dragSize
);
231 view
->FillRect(fXScrollDragZone1
);
232 fXScrollDragZone2
= BRect(fPadRect
.left
+ fXScrollRange
- dragSize
,
233 fPadRect
.bottom
- dragSize
,
234 fPadRect
.left
+ fXScrollRange
+ dragSize
,
235 fPadRect
.bottom
+ dragSize
);
236 view
->FillRect(fXScrollDragZone2
);
238 // y scroll range line
239 view
->StrokeLine(BPoint(fPadRect
.left
, fPadRect
.top
+ fYScrollRange
),
240 BPoint(fPadRect
.right
, fPadRect
.top
+ fYScrollRange
));
242 fYScrollDragZone
= BRect(fPadRect
.left
- dragSize
,
243 fPadRect
.top
+ fYScrollRange
- dragSize
,
244 fPadRect
.right
+ dragSize
,
245 fPadRect
.top
+ fYScrollRange
+ dragSize
);
246 fYScrollDragZone1
= BRect(fPadRect
.left
- dragSize
,
247 fPadRect
.top
+ fYScrollRange
- dragSize
, fPadRect
.left
+ dragSize
,
248 fPadRect
.top
+ fYScrollRange
+ dragSize
);
249 view
->FillRect(fYScrollDragZone1
);
250 fYScrollDragZone2
= BRect(fPadRect
.right
- dragSize
,
251 fPadRect
.top
+ fYScrollRange
- dragSize
, fPadRect
.right
+ dragSize
,
252 fPadRect
.top
+ fYScrollRange
+ dragSize
);
253 view
->FillRect(fYScrollDragZone2
);
256 fOffScreenBitmap
->Unlock();
257 DrawBitmap(fOffScreenBitmap
, B_ORIGIN
);
264 // #pragma mark - TouchpadPrefView
267 TouchpadPrefView::TouchpadPrefView()
273 SetValues(&fTouchpadPref
.Settings());
277 TouchpadPrefView::~TouchpadPrefView()
283 TouchpadPrefView::MessageReceived(BMessage
* message
)
285 touchpad_settings
& settings
= fTouchpadPref
.Settings();
287 switch (message
->what
) {
288 case SCROLL_AREA_CHANGED
:
289 settings
.scroll_rightrange
= fTouchpadView
->GetRightScrollRatio();
290 settings
.scroll_bottomrange
= fTouchpadView
->GetBottomScrollRatio();
291 fRevertButton
->SetEnabled(true);
292 fTouchpadPref
.UpdateSettings();
295 case SCROLL_CONTROL_CHANGED
:
296 settings
.scroll_twofinger
= fTwoFingerBox
->Value() == B_CONTROL_ON
;
297 settings
.scroll_twofinger_horizontal
298 = fTwoFingerHorizontalBox
->Value() == B_CONTROL_ON
;
299 settings
.scroll_acceleration
= fScrollAccelSlider
->Value();
300 settings
.scroll_xstepsize
= (20 - fScrollStepXSlider
->Value()) * 3;
301 settings
.scroll_ystepsize
= (20 - fScrollStepYSlider
->Value()) * 3;
302 fRevertButton
->SetEnabled(true);
303 fTwoFingerHorizontalBox
->SetEnabled(settings
.scroll_twofinger
);
304 fTouchpadPref
.UpdateSettings();
307 case TAP_CONTROL_CHANGED
:
308 settings
.tapgesture_sensibility
= fTapSlider
->Value();
309 fRevertButton
->SetEnabled(true);
310 fTouchpadPref
.UpdateSettings();
313 case DEFAULT_SETTINGS
:
314 fTouchpadPref
.Defaults();
315 fRevertButton
->SetEnabled(true);
316 fTouchpadPref
.UpdateSettings();
317 SetValues(&settings
);
320 case REVERT_SETTINGS
:
321 fTouchpadPref
.Revert();
322 fTouchpadPref
.UpdateSettings();
323 fRevertButton
->SetEnabled(false);
324 SetValues(&settings
);
328 BView::MessageReceived(message
);
334 TouchpadPrefView::AttachedToWindow()
336 fTouchpadView
->SetTarget(this);
337 fTwoFingerBox
->SetTarget(this);
338 fTwoFingerHorizontalBox
->SetTarget(this);
339 fScrollStepXSlider
->SetTarget(this);
340 fScrollStepYSlider
->SetTarget(this);
341 fScrollAccelSlider
->SetTarget(this);
342 fTapSlider
->SetTarget(this);
343 fDefaultButton
->SetTarget(this);
344 fRevertButton
->SetTarget(this);
345 BSize size
= PreferredSize();
346 Window()->ResizeTo(size
.width
, size
.height
);
348 BPoint position
= fTouchpadPref
.WindowPosition();
349 // center window on screen if it had a bad position
350 if (position
.x
< 0 && position
.y
< 0)
351 Window()->CenterOnScreen();
353 Window()->MoveTo(position
);
358 TouchpadPrefView::DetachedFromWindow()
360 fTouchpadPref
.SetWindowPosition(Window()->Frame().LeftTop());
365 TouchpadPrefView::SetupView()
367 SetLayout(new BGroupLayout(B_VERTICAL
));
368 BBox
* scrollBox
= new BBox("Touchpad");
369 scrollBox
->SetLabel(B_TRANSLATE("Scrolling"));
371 fTouchpadView
= new TouchpadView(BRect(0, 0, 130, 120));
372 fTouchpadView
->SetExplicitMaxSize(BSize(130, 120));
374 // Create the "Mouse Speed" slider...
375 fScrollAccelSlider
= new BSlider("scroll_accel",
376 B_TRANSLATE("Acceleration"),
377 new BMessage(SCROLL_CONTROL_CHANGED
), 0, 20, B_HORIZONTAL
);
378 fScrollAccelSlider
->SetHashMarks(B_HASH_MARKS_BOTTOM
);
379 fScrollAccelSlider
->SetHashMarkCount(7);
380 fScrollAccelSlider
->SetLimitLabels(B_TRANSLATE("Slow"),
381 B_TRANSLATE("Fast"));
382 fScrollAccelSlider
->SetExplicitMinSize(BSize(150, B_SIZE_UNSET
));
384 fScrollStepXSlider
= new BSlider("scroll_stepX",
385 B_TRANSLATE("Horizontal"),
386 new BMessage(SCROLL_CONTROL_CHANGED
),
387 0, 20, B_HORIZONTAL
);
388 fScrollStepXSlider
->SetHashMarks(B_HASH_MARKS_BOTTOM
);
389 fScrollStepXSlider
->SetHashMarkCount(7);
390 fScrollStepXSlider
->SetLimitLabels(B_TRANSLATE("Slow"),
391 B_TRANSLATE("Fast"));
393 fScrollStepYSlider
= new BSlider("scroll_stepY",
394 B_TRANSLATE("Vertical"),
395 new BMessage(SCROLL_CONTROL_CHANGED
), 0, 20, B_HORIZONTAL
);
396 fScrollStepYSlider
->SetHashMarks(B_HASH_MARKS_BOTTOM
);
397 fScrollStepYSlider
->SetHashMarkCount(7);
398 fScrollStepYSlider
->SetLimitLabels(B_TRANSLATE("Slow"),
399 B_TRANSLATE("Fast"));
401 fTwoFingerBox
= new BCheckBox(B_TRANSLATE("Two finger scrolling"),
402 new BMessage(SCROLL_CONTROL_CHANGED
));
403 fTwoFingerHorizontalBox
= new BCheckBox(
404 B_TRANSLATE("Horizontal scrolling"),
405 new BMessage(SCROLL_CONTROL_CHANGED
));
407 float spacing
= be_control_look
->DefaultItemSpacing();
409 BView
* scrollPrefLeftLayout
410 = BLayoutBuilder::Group
<>(B_VERTICAL
, 0)
414 .AddGroup(B_HORIZONTAL
, 0)
415 .AddStrut(spacing
* 2)
416 .Add(fTwoFingerHorizontalBox
)
421 BGroupView
* scrollPrefRightLayout
= new BGroupView(B_VERTICAL
);
422 scrollPrefRightLayout
->AddChild(fScrollAccelSlider
);
423 scrollPrefRightLayout
->AddChild(fScrollStepXSlider
);
424 scrollPrefRightLayout
->AddChild(fScrollStepYSlider
);
426 BGroupLayout
* scrollPrefLayout
= new BGroupLayout(B_HORIZONTAL
);
427 scrollPrefLayout
->SetSpacing(spacing
);
428 scrollPrefLayout
->SetInsets(spacing
,
429 scrollBox
->TopBorderOffset() * 2 + spacing
, spacing
, spacing
);
430 scrollBox
->SetLayout(scrollPrefLayout
);
432 scrollPrefLayout
->AddView(scrollPrefLeftLayout
);
433 scrollPrefLayout
->AddItem(BSpaceLayoutItem::CreateVerticalStrut(spacing
435 scrollPrefLayout
->AddView(scrollPrefRightLayout
);
437 BBox
* tapBox
= new BBox("tapbox");
438 tapBox
->SetLabel(B_TRANSLATE("Tapping"));
440 BGroupLayout
* tapPrefLayout
= new BGroupLayout(B_HORIZONTAL
);
441 tapPrefLayout
->SetInsets(spacing
, tapBox
->TopBorderOffset() * 2 + spacing
,
443 tapBox
->SetLayout(tapPrefLayout
);
445 fTapSlider
= new BSlider("tap_sens", B_TRANSLATE("Sensitivity"),
446 new BMessage(TAP_CONTROL_CHANGED
), 0, spacing
* 2, B_HORIZONTAL
);
447 fTapSlider
->SetHashMarks(B_HASH_MARKS_BOTTOM
);
448 fTapSlider
->SetHashMarkCount(7);
449 fTapSlider
->SetLimitLabels(B_TRANSLATE("Off"), B_TRANSLATE("High"));
451 tapPrefLayout
->AddView(fTapSlider
);
453 fDefaultButton
= new BButton(B_TRANSLATE("Defaults"),
454 new BMessage(DEFAULT_SETTINGS
));
456 fRevertButton
= new BButton(B_TRANSLATE("Revert"),
457 new BMessage(REVERT_SETTINGS
));
458 fRevertButton
->SetEnabled(false);
460 BLayoutBuilder::Group
<>(this, B_VERTICAL
)
461 .SetInsets(B_USE_WINDOW_SPACING
)
464 .AddGroup(B_HORIZONTAL
)
474 TouchpadPrefView::SetValues(touchpad_settings
* settings
)
476 fTouchpadView
->SetValues(settings
->scroll_rightrange
,
477 settings
->scroll_bottomrange
);
478 fTwoFingerBox
->SetValue(settings
->scroll_twofinger
479 ? B_CONTROL_ON
: B_CONTROL_OFF
);
480 fTwoFingerHorizontalBox
->SetValue(settings
->scroll_twofinger_horizontal
481 ? B_CONTROL_ON
: B_CONTROL_OFF
);
482 fTwoFingerHorizontalBox
->SetEnabled(settings
->scroll_twofinger
);
483 fScrollStepXSlider
->SetValue(20 - settings
->scroll_xstepsize
/ 2);
484 fScrollStepYSlider
->SetValue(20 - settings
->scroll_ystepsize
/ 2);
485 fScrollAccelSlider
->SetValue(settings
->scroll_acceleration
);
486 fTapSlider
->SetValue(settings
->tapgesture_sensibility
);