xref: /haiku/src/preferences/input/InputWindow.cpp (revision 2e68fbd20741c99d199045a0599e614ca9a2e07e)
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 <SplitView.h>
22 #include <Screen.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(32 + fDeviceListView->StringWidth("Extended PS/2 Mouse 1"),
48 			B_SIZE_UNSET));
49 
50 	BScrollView* scrollView = new BScrollView("scrollView", fDeviceListView,
51 		0, false, B_FANCY_BORDER);
52 	fCardView = new BCardView();
53 
54 	BLayoutBuilder::Group<>(this, B_HORIZONTAL, 10)
55 		.SetInsets(B_USE_WINDOW_SPACING)
56 		.Add(scrollView, 1)
57 		.Add(fCardView, 3);
58 
59 	FindDevice();
60 }
61 
62 void
63 InputWindow::MessageReceived(BMessage* message)
64 {
65 	switch (message->what) {
66 		case ITEM_SELECTED:
67 		{
68 			int32 index = message->GetInt32("index", 0);
69 			if (index >= 0)
70 				fCardView->CardLayout()->SetVisibleItem(index);
71 			break;
72 		}
73 		case kMsgMouseType:
74 		case kMsgMouseMap:
75 		case kMsgMouseFocusMode:
76 		case kMsgFollowsMouseMode:
77 		case kMsgAcceptFirstClick:
78 		case kMsgDoubleClickSpeed:
79 		case kMsgMouseSpeed:
80 		case kMsgAccelerationFactor:
81 		case kMsgDefaults:
82 		case kMsgRevert:
83 		{
84 			PostMessage(message,
85 				fCardView->CardLayout()->VisibleItem()->View());
86 			break;
87 		}
88 		case SCROLL_AREA_CHANGED:
89 		case SCROLL_CONTROL_CHANGED:
90 		case TAP_CONTROL_CHANGED:
91 		case DEFAULT_SETTINGS:
92 		case REVERT_SETTINGS:
93 		{
94 			PostMessage(message,
95 				fCardView->CardLayout()->VisibleItem()->View());
96 			break;
97 		}
98 		case kMsgSliderrepeatrate:
99 		case kMsgSliderdelayrate:
100 		{
101 			PostMessage(message,
102 				fCardView->CardLayout()->VisibleItem()->View());
103 			break;
104 		}
105 
106 		case IS_NOTIFY_DEVICE:
107 		{
108 			bool added = message->FindBool("added");
109 			BString name = message->FindString("name");
110 
111 			if (added) {
112 				BInputDevice* device = find_input_device(name);
113 				if (device)
114 					AddDevice(device);
115 			} else {
116 				for (int i = 0; i < fDeviceListView->CountItems(); i++) {
117 					DeviceListItemView* item =
118 						dynamic_cast<DeviceListItemView*>(
119 							fDeviceListView->ItemAt(i));
120 					if (item != NULL && item->Label() == name) {
121 						fDeviceListView->RemoveItem(i);
122 						BView* settings = fCardView->ChildAt(i);
123 						fCardView->RemoveChild(settings);
124 						delete settings;
125 						break;
126 					}
127 				}
128 			}
129 
130 			break;
131 		}
132 
133 		default:
134 			BWindow::MessageReceived(message);
135 			break;
136 	}
137 }
138 
139 
140 void
141 InputWindow::Show()
142 {
143 	CenterOnScreen();
144 	BWindow::Show();
145 	watch_input_devices(this, true);
146 }
147 
148 
149 void
150 InputWindow::Hide()
151 {
152 	BWindow::Hide();
153 	watch_input_devices(this, false);
154 }
155 
156 
157 status_t
158 InputWindow::FindDevice()
159 {
160 	BList devList;
161 	status_t status = get_input_devices(&devList);
162 	if (status != B_OK)
163 		return status;
164 
165 	int32 i = 0;
166 
167 	while (true) {
168 		BInputDevice* dev = (BInputDevice*)devList.ItemAt(i);
169 		if (dev == NULL) {
170 			break;
171 		}
172 		i++;
173 
174 		AddDevice(dev);
175 	}
176 
177 	return B_OK;
178 }
179 
180 
181 void
182 InputWindow::AddDevice(BInputDevice* dev)
183 {
184 	BString name = dev->Name();
185 
186 	if (dev->Type() == B_POINTING_DEVICE
187 		&& name.FindFirst("Touchpad") >= 0) {
188 		TouchpadPrefView* view = new TouchpadPrefView(dev);
189 		fCardView->AddChild(view);
190 
191 		DeviceListItemView* touchpad = new DeviceListItemView(
192 			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(
202 			name, MOUSE_TYPE);
203 		fDeviceListView->AddItem(mouse);
204 	} else if (dev->Type() == B_KEYBOARD_DEVICE) {
205 		InputKeyboard* view = new InputKeyboard(dev);
206 		fCardView->AddChild(view);
207 
208 		DeviceListItemView* keyboard = new DeviceListItemView(
209 			name, KEYBOARD_TYPE);
210 		fDeviceListView->AddItem(keyboard);
211 	} else {
212 		delete dev;
213 	}
214 }
215