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