xref: /haiku/src/preferences/input/InputWindow.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 /*
2  * Copyright 2019-2020, Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Preetpal Kaur <preetpalok123@gmail.com>
7  *		Adrien Destugues <pulkomandy@gmail.com>
8  */
9 
10 
11 #include <Alert.h>
12 #include <Alignment.h>
13 #include <Application.h>
14 #include <Button.h>
15 #include <CardLayout.h>
16 #include <CardView.h>
17 #include <Catalog.h>
18 #include <Control.h>
19 #include <ControlLook.h>
20 #include <LayoutBuilder.h>
21 #include <Screen.h>
22 #include <SplitView.h>
23 
24 #include <private/input/InputServerTypes.h>
25 
26 #include "InputConstants.h"
27 #include "InputDeviceView.h"
28 #include "InputMouse.h"
29 #include "InputTouchpadPref.h"
30 #include "InputWindow.h"
31 #include "MouseSettings.h"
32 #include "SettingsView.h"
33 
34 #undef B_TRANSLATION_CONTEXT
35 #define B_TRANSLATION_CONTEXT "InputWindow"
36 
37 
38 InputWindow::InputWindow(BRect rect)
39 	:
40 	BWindow(rect, B_TRANSLATE_SYSTEM_NAME("Input"), B_TITLED_WINDOW,
41 		B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS
42 			| B_AUTO_UPDATE_SIZE_LIMITS | B_QUIT_ON_WINDOW_CLOSE)
43 {
44 	fDeviceListView = new BListView(B_TRANSLATE("Device List"));
45 	fDeviceListView->SetSelectionMessage(new BMessage(ITEM_SELECTED));
46 	fDeviceListView->SetExplicitMinSize(
47 		BSize(be_control_look->ComposeIconSize(32).Width()
48 				+ fDeviceListView->StringWidth("Extended PS/2 Mouse 1"),
49 			B_SIZE_UNSET));
50 
51 	BScrollView* scrollView = new BScrollView(
52 		"scrollView", fDeviceListView, 0, false, B_FANCY_BORDER);
53 	fCardView = new BCardView();
54 
55 	BLayoutBuilder::Group<>(this, B_HORIZONTAL, 10)
56 		.SetInsets(B_USE_WINDOW_SPACING)
57 		.Add(scrollView, 1)
58 		.Add(fCardView, 3);
59 
60 	FindDevice();
61 }
62 
63 
64 void
65 InputWindow::MessageReceived(BMessage* message)
66 {
67 	switch (message->what) {
68 		case ITEM_SELECTED:
69 		{
70 			int32 index = message->GetInt32("index", 0);
71 			if (index >= 0)
72 				fCardView->CardLayout()->SetVisibleItem(index);
73 			break;
74 		}
75 		case kMsgMouseType:
76 		case kMsgMouseMap:
77 		case kMsgMouseFocusMode:
78 		case kMsgFollowsMouseMode:
79 		case kMsgAcceptFirstClick:
80 		case kMsgDoubleClickSpeed:
81 		case kMsgMouseSpeed:
82 		case kMsgAccelerationFactor:
83 		case kMsgDefaults:
84 		case kMsgRevert:
85 		{
86 			PostMessage(
87 				message, fCardView->CardLayout()->VisibleItem()->View());
88 			break;
89 		}
90 		case SCROLL_AREA_CHANGED:
91 		case SCROLL_CONTROL_CHANGED:
92 		case TAP_CONTROL_CHANGED:
93 		case DEFAULT_SETTINGS:
94 		case REVERT_SETTINGS:
95 		{
96 			PostMessage(
97 				message, fCardView->CardLayout()->VisibleItem()->View());
98 			break;
99 		}
100 		case kMsgSliderrepeatrate:
101 		case kMsgSliderdelayrate:
102 		{
103 			PostMessage(
104 				message, fCardView->CardLayout()->VisibleItem()->View());
105 			break;
106 		}
107 
108 		case B_INPUT_DEVICES_CHANGED:
109 		{
110 			int32 operation = message->FindInt32("be:opcode");
111 			BString name = message->FindString("be:device_name");
112 
113 			if (operation == B_INPUT_DEVICE_ADDED) {
114 				BInputDevice* device = find_input_device(name);
115 				if (device)
116 					AddDevice(device);
117 			} else if (operation == B_INPUT_DEVICE_REMOVED) {
118 				for (int i = 0; i < fDeviceListView->CountItems(); i++) {
119 					DeviceListItemView* item
120 						= dynamic_cast<DeviceListItemView*>(
121 							fDeviceListView->ItemAt(i));
122 					if (item != NULL && item->Label() == name) {
123 						fDeviceListView->RemoveItem(i);
124 						BView* settings = fCardView->ChildAt(i);
125 						fCardView->RemoveChild(settings);
126 						delete settings;
127 						break;
128 					}
129 				}
130 			}
131 
132 			break;
133 		}
134 
135 		default:
136 			BWindow::MessageReceived(message);
137 			break;
138 	}
139 }
140 
141 
142 void
143 InputWindow::Show()
144 {
145 	CenterOnScreen();
146 	BWindow::Show();
147 	watch_input_devices(this, true);
148 }
149 
150 
151 void
152 InputWindow::Hide()
153 {
154 	BWindow::Hide();
155 	watch_input_devices(this, false);
156 }
157 
158 
159 status_t
160 InputWindow::FindDevice()
161 {
162 	BList devList;
163 	status_t status = get_input_devices(&devList);
164 	if (status != B_OK)
165 		return status;
166 
167 	int32 i = 0;
168 
169 	while (true) {
170 		BInputDevice* dev = (BInputDevice*)devList.ItemAt(i);
171 		if (dev == NULL)
172 			break;
173 		i++;
174 
175 		AddDevice(dev);
176 	}
177 
178 	return B_OK;
179 }
180 
181 
182 void
183 InputWindow::AddDevice(BInputDevice* dev)
184 {
185 	BString name = dev->Name();
186 
187 	if (dev->Type() == B_POINTING_DEVICE && name.FindFirst("Touchpad") >= 0) {
188 		TouchpadPrefView* view = new TouchpadPrefView(dev);
189 		fCardView->AddChild(view);
190 
191 		DeviceListItemView* touchpad
192 			= new DeviceListItemView(name, TOUCHPAD_TYPE);
193 		fDeviceListView->AddItem(touchpad);
194 	} else if (dev->Type() == B_POINTING_DEVICE) {
195 		MouseSettings* settings;
196 		settings = fMultipleMouseSettings.AddMouseSettings(name);
197 
198 		InputMouse* view = new InputMouse(dev, settings);
199 		fCardView->AddChild(view);
200 
201 		DeviceListItemView* mouse = new DeviceListItemView(name, MOUSE_TYPE);
202 		fDeviceListView->AddItem(mouse);
203 	} else if (dev->Type() == B_KEYBOARD_DEVICE) {
204 		InputKeyboard* view = new InputKeyboard(dev);
205 		fCardView->AddChild(view);
206 
207 		DeviceListItemView* keyboard
208 			= new DeviceListItemView(name, KEYBOARD_TYPE);
209 		fDeviceListView->AddItem(keyboard);
210 	} else
211 		delete dev;
212 }
213