xref: /haiku/src/preferences/input/InputWindow.cpp (revision 4a850ca730d8282b5b924e49e09b4ba4d6db7f54)
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(32 + fDeviceListView->StringWidth("Extended PS/2 Mouse 1"),
48 			B_SIZE_UNSET));
49 
50 	BScrollView* scrollView = new BScrollView(
51 		"scrollView", fDeviceListView, 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 
63 void
64 InputWindow::MessageReceived(BMessage* message)
65 {
66 	switch (message->what) {
67 		case ITEM_SELECTED:
68 		{
69 			int32 index = message->GetInt32("index", 0);
70 			if (index >= 0)
71 				fCardView->CardLayout()->SetVisibleItem(index);
72 			break;
73 		}
74 		case kMsgMouseType:
75 		case kMsgMouseMap:
76 		case kMsgMouseFocusMode:
77 		case kMsgFollowsMouseMode:
78 		case kMsgAcceptFirstClick:
79 		case kMsgDoubleClickSpeed:
80 		case kMsgMouseSpeed:
81 		case kMsgAccelerationFactor:
82 		case kMsgDefaults:
83 		case kMsgRevert:
84 		{
85 			PostMessage(
86 				message, fCardView->CardLayout()->VisibleItem()->View());
87 			break;
88 		}
89 		case SCROLL_AREA_CHANGED:
90 		case SCROLL_CONTROL_CHANGED:
91 		case TAP_CONTROL_CHANGED:
92 		case DEFAULT_SETTINGS:
93 		case REVERT_SETTINGS:
94 		{
95 			PostMessage(
96 				message, fCardView->CardLayout()->VisibleItem()->View());
97 			break;
98 		}
99 		case kMsgSliderrepeatrate:
100 		case kMsgSliderdelayrate:
101 		{
102 			PostMessage(
103 				message, fCardView->CardLayout()->VisibleItem()->View());
104 			break;
105 		}
106 
107 		case B_INPUT_DEVICES_CHANGED:
108 		{
109 			int32 operation = message->FindInt32("be:opcode");
110 			BString name = message->FindString("be:device_name");
111 
112 			if (operation == B_INPUT_DEVICE_ADDED) {
113 				BInputDevice* device = find_input_device(name);
114 				if (device)
115 					AddDevice(device);
116 			} else if (operation == B_INPUT_DEVICE_REMOVED) {
117 				for (int i = 0; i < fDeviceListView->CountItems(); i++) {
118 					DeviceListItemView* item
119 						= dynamic_cast<DeviceListItemView*>(
120 							fDeviceListView->ItemAt(i));
121 					if (item != NULL && item->Label() == name) {
122 						fDeviceListView->RemoveItem(i);
123 						BView* settings = fCardView->ChildAt(i);
124 						fCardView->RemoveChild(settings);
125 						delete settings;
126 						break;
127 					}
128 				}
129 			}
130 
131 			break;
132 		}
133 
134 		default:
135 			BWindow::MessageReceived(message);
136 			break;
137 	}
138 }
139 
140 
141 void
142 InputWindow::Show()
143 {
144 	CenterOnScreen();
145 	BWindow::Show();
146 	watch_input_devices(this, true);
147 }
148 
149 
150 void
151 InputWindow::Hide()
152 {
153 	BWindow::Hide();
154 	watch_input_devices(this, false);
155 }
156 
157 
158 status_t
159 InputWindow::FindDevice()
160 {
161 	BList devList;
162 	status_t status = get_input_devices(&devList);
163 	if (status != B_OK)
164 		return status;
165 
166 	int32 i = 0;
167 
168 	while (true) {
169 		BInputDevice* dev = (BInputDevice*)devList.ItemAt(i);
170 		if (dev == NULL)
171 			break;
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 && name.FindFirst("Touchpad") >= 0) {
187 		TouchpadPrefView* view = new TouchpadPrefView(dev);
188 		fCardView->AddChild(view);
189 
190 		DeviceListItemView* touchpad
191 			= new DeviceListItemView(name, TOUCHPAD_TYPE);
192 		fDeviceListView->AddItem(touchpad);
193 	} else if (dev->Type() == B_POINTING_DEVICE) {
194 		MouseSettings* settings;
195 		settings = fMultipleMouseSettings.AddMouseSettings(name);
196 
197 		InputMouse* view = new InputMouse(dev, settings);
198 		fCardView->AddChild(view);
199 
200 		DeviceListItemView* mouse = new DeviceListItemView(name, MOUSE_TYPE);
201 		fDeviceListView->AddItem(mouse);
202 	} else if (dev->Type() == B_KEYBOARD_DEVICE) {
203 		InputKeyboard* view = new InputKeyboard(dev);
204 		fCardView->AddChild(view);
205 
206 		DeviceListItemView* keyboard
207 			= new DeviceListItemView(name, KEYBOARD_TYPE);
208 		fDeviceListView->AddItem(keyboard);
209 	} else
210 		delete dev;
211 }
212