1 /* 2 * Copyright 2019, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Author: 6 * Preetpal Kaur <preetpalok123@gmail.com> 7 */ 8 9 10 #include "InputMouse.h" 11 12 #include <Bitmap.h> 13 #include <Box.h> 14 #include <Button.h> 15 #include <Catalog.h> 16 #include <ControlLook.h> 17 #include <Debug.h> 18 #include <InterfaceDefs.h> 19 #include <LayoutBuilder.h> 20 #include <Locale.h> 21 #include <MenuField.h> 22 #include <MenuItem.h> 23 #include <PopUpMenu.h> 24 #include <SeparatorView.h> 25 #include <Slider.h> 26 #include <TextControl.h> 27 #include <TranslationUtils.h> 28 #include <Window.h> 29 30 #include "InputConstants.h" 31 #include "MouseSettings.h" 32 #include "MouseView.h" 33 34 35 static int32 36 mouse_mode_to_index(mode_mouse mode) 37 { 38 switch (mode) { 39 case B_NORMAL_MOUSE: 40 default: 41 return 0; 42 case B_CLICK_TO_FOCUS_MOUSE: 43 return 1; 44 case B_FOCUS_FOLLOWS_MOUSE: 45 return 2; 46 } 47 } 48 49 50 static int32 51 focus_follows_mouse_mode_to_index(mode_focus_follows_mouse mode) 52 { 53 switch (mode) { 54 case B_NORMAL_FOCUS_FOLLOWS_MOUSE: 55 default: 56 return 0; 57 case B_WARP_FOCUS_FOLLOWS_MOUSE: 58 return 1; 59 case B_INSTANT_WARP_FOCUS_FOLLOWS_MOUSE: 60 return 2; 61 } 62 } 63 64 65 // #pragma mark - 66 67 #undef B_TRANSLATION_CONTEXT 68 #define B_TRANSLATION_CONTEXT "SettingsView" 69 70 SettingsView::SettingsView(MouseSettings& settings) 71 : BBox("main_view"), 72 fSettings(settings) 73 { 74 // Add the "Mouse Type" pop up menu 75 fTypeMenu = new BOptionPopUp("type", B_TRANSLATE("Mouse type:"), 76 new BMessage(kMsgMouseType)); 77 fTypeMenu->AddOption(B_TRANSLATE("1-Button"), 1); 78 fTypeMenu->AddOption(B_TRANSLATE("2-Button"), 2); 79 fTypeMenu->AddOption(B_TRANSLATE("3-Button"), 3); 80 fTypeMenu->AddOption(B_TRANSLATE("4-Button"), 4); 81 fTypeMenu->AddOption(B_TRANSLATE("5-Button"), 5); 82 fTypeMenu->AddOption(B_TRANSLATE("6-Button"), 6); 83 84 // Create the "Double-click speed slider... 85 fClickSpeedSlider = new BSlider("double_click_speed", 86 B_TRANSLATE("Double-click speed"), new BMessage(kMsgDoubleClickSpeed), 87 0, 1000, B_HORIZONTAL); 88 fClickSpeedSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 89 fClickSpeedSlider->SetHashMarkCount(7); 90 91 // Create the "Mouse Speed" slider... 92 fMouseSpeedSlider = new BSlider("mouse_speed", B_TRANSLATE("Mouse speed"), 93 new BMessage(kMsgMouseSpeed), 0, 1000, B_HORIZONTAL); 94 fMouseSpeedSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 95 fMouseSpeedSlider->SetHashMarkCount(7); 96 97 // Create the "Mouse Acceleration" slider... 98 fAccelerationSlider = new BSlider("mouse_acceleration", 99 B_TRANSLATE("Mouse acceleration"), 100 new BMessage(kMsgAccelerationFactor), 0, 1000, B_HORIZONTAL); 101 fAccelerationSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 102 fAccelerationSlider->SetHashMarkCount(7); 103 104 fMouseView = new MouseView(fSettings); 105 106 // Create the "Double-click test area" text box... 107 const char* label = B_TRANSLATE("Double-click test area"); 108 BTextControl* doubleClickTextControl = new BTextControl(NULL, 109 label, NULL); 110 doubleClickTextControl->SetAlignment(B_ALIGN_LEFT, B_ALIGN_CENTER); 111 doubleClickTextControl->SetExplicitMinSize( 112 BSize(StringWidth(label), B_SIZE_UNSET)); 113 114 // Add the "Mouse focus mode" pop up menu 115 fFocusMenu = new BPopUpMenu(B_TRANSLATE("Click to focus and raise")); 116 117 const char *focusLabels[] = {B_TRANSLATE_MARK("Click to focus and raise"), 118 B_TRANSLATE_MARK("Click to focus"), 119 B_TRANSLATE_MARK("Focus follows mouse")}; 120 const mode_mouse focusModes[] = {B_NORMAL_MOUSE, B_CLICK_TO_FOCUS_MOUSE, 121 B_FOCUS_FOLLOWS_MOUSE}; 122 123 for (int i = 0; i < 3; i++) { 124 BMessage* message = new BMessage(kMsgMouseFocusMode); 125 message->AddInt32("mode", focusModes[i]); 126 127 fFocusMenu->AddItem(new BMenuItem(B_TRANSLATE_NOCOLLECT(focusLabels[i]), 128 message)); 129 } 130 131 BMenuField* focusField = new BMenuField(B_TRANSLATE("Focus mode:"), 132 fFocusMenu); 133 focusField->SetAlignment(B_ALIGN_LEFT); 134 135 // Add the "Focus follows mouse mode" pop up menu 136 fFocusFollowsMouseMenu = new BPopUpMenu(B_TRANSLATE("Normal")); 137 138 const char *focusFollowsMouseLabels[] = {B_TRANSLATE_MARK("Normal"), 139 B_TRANSLATE_MARK("Warp"), B_TRANSLATE_MARK("Instant warp")}; 140 const mode_focus_follows_mouse focusFollowsMouseModes[] 141 = {B_NORMAL_FOCUS_FOLLOWS_MOUSE, B_WARP_FOCUS_FOLLOWS_MOUSE, 142 B_INSTANT_WARP_FOCUS_FOLLOWS_MOUSE}; 143 144 for (int i = 0; i < 3; i++) { 145 BMessage* message = new BMessage(kMsgFollowsMouseMode); 146 message->AddInt32("mode_focus_follows_mouse", 147 focusFollowsMouseModes[i]); 148 149 fFocusFollowsMouseMenu->AddItem(new BMenuItem( 150 B_TRANSLATE_NOCOLLECT(focusFollowsMouseLabels[i]), message)); 151 } 152 153 BMenuField* focusFollowsMouseField = new BMenuField( 154 "Focus follows mouse mode:", fFocusFollowsMouseMenu); 155 focusFollowsMouseField->SetAlignment(B_ALIGN_RIGHT); 156 157 // Add the "Click-through" check box 158 fAcceptFirstClickBox = new BCheckBox(B_TRANSLATE("Accept first click"), 159 new BMessage(kMsgAcceptFirstClick)); 160 161 // Build the layout 162 163 // Layout is : 164 // A | B 165 // ----- 166 // C 167 168 BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING) 169 // Horizontal : A|B 170 .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 171 172 // Vertical block A: mouse type/view/test 173 .AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING) 174 .Add(fTypeMenu) 175 .AddGroup(B_HORIZONTAL, 0) 176 .AddGlue() 177 .Add(fMouseView) 178 .AddGlue() 179 .End() 180 .AddGlue() 181 .Add(doubleClickTextControl) 182 .End() 183 .Add(new BSeparatorView(B_VERTICAL)) 184 185 // Vertical block B: speed settings 186 .AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING, 3) 187 .AddGroup(B_HORIZONTAL, 0) 188 .Add(fClickSpeedSlider) 189 .End() 190 .AddGroup(B_HORIZONTAL, 0) 191 .Add(fMouseSpeedSlider) 192 .End() 193 .AddGroup(B_HORIZONTAL, 0) 194 .Add(fAccelerationSlider) 195 .End() 196 .End() 197 .End() 198 .AddStrut(B_USE_DEFAULT_SPACING) 199 200 // Horizontal Block C: focus mode 201 .AddGroup(B_HORIZONTAL, B_USE_SMALL_SPACING) 202 .Add(focusField) 203 .AddGlue() 204 .AddGroup(B_VERTICAL, 0) 205 .Add(fAcceptFirstClickBox) 206 .End() 207 .End(); 208 209 SetBorder(B_NO_BORDER); 210 } 211 212 213 SettingsView::~SettingsView() 214 { 215 216 } 217 218 219 void 220 SettingsView::AttachedToWindow() 221 { 222 UpdateFromSettings(); 223 } 224 225 226 void 227 SettingsView::SetMouseType(int32 type) 228 { 229 fMouseView->SetMouseType(type); 230 } 231 232 233 void 234 SettingsView::MouseMapUpdated() 235 { 236 fMouseView->MouseMapUpdated(); 237 } 238 239 240 void 241 SettingsView::UpdateFromSettings() 242 { 243 int32 value = int32(fSettings.ClickSpeed() / 1000); 244 // slow = 1000000, fast = 0 245 fClickSpeedSlider->SetValue(value); 246 247 value = int32((log(fSettings.MouseSpeed() / 8192.0) / log(2)) * 1000 / 6); 248 // slow = 8192, fast = 524287 249 fMouseSpeedSlider->SetValue(value); 250 251 value = int32(sqrt(fSettings.AccelerationFactor() / 16384.0) * 1000 / 4); 252 // slow = 0, fast = 262144 253 fAccelerationSlider->SetValue(value); 254 255 fTypeMenu->SelectOptionFor(fSettings.MouseType()); 256 fMouseView->SetMouseType(fSettings.MouseType()); 257 258 BMenuItem* item = fFocusMenu->ItemAt( 259 mouse_mode_to_index(fSettings.MouseMode())); 260 if (item != NULL) 261 item->SetMarked(true); 262 263 item = fFocusFollowsMouseMenu->ItemAt( 264 focus_follows_mouse_mode_to_index(fSettings.FocusFollowsMouseMode())); 265 if (item != NULL) 266 item->SetMarked(true); 267 268 fFocusFollowsMouseMenu->SetEnabled(fSettings.MouseMode() 269 == B_FOCUS_FOLLOWS_MOUSE); 270 271 fAcceptFirstClickBox->SetValue(fSettings.AcceptFirstClick() 272 ? B_CONTROL_ON : B_CONTROL_OFF); 273 fAcceptFirstClickBox->SetEnabled(fSettings.MouseMode() 274 != B_FOCUS_FOLLOWS_MOUSE); 275 } 276