1a10cf76eSAxel Dörfler /* 2a10cf76eSAxel Dörfler * Copyright 2001-2005, Haiku. 3a10cf76eSAxel Dörfler * Distributed under the terms of the MIT License. 4a10cf76eSAxel Dörfler * 5a10cf76eSAxel Dörfler * Authors: 6a10cf76eSAxel Dörfler * Rafael Romo 7a10cf76eSAxel Dörfler * Stefano Ceccherini (burton666@libero.it) 8a10cf76eSAxel Dörfler * Andrew Bachmann 9a10cf76eSAxel Dörfler * Thomas Kurschel 10a10cf76eSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de 11a10cf76eSAxel Dörfler */ 12a10cf76eSAxel Dörfler 13a10cf76eSAxel Dörfler 14a10cf76eSAxel Dörfler #include <Alert.h> 15a10cf76eSAxel Dörfler #include <Application.h> 16a10cf76eSAxel Dörfler #include <Box.h> 17a10cf76eSAxel Dörfler #include <Button.h> 18a10cf76eSAxel Dörfler #include <InterfaceDefs.h> 19a10cf76eSAxel Dörfler #include <MenuItem.h> 20a10cf76eSAxel Dörfler #include <MenuField.h> 21a10cf76eSAxel Dörfler #include <Messenger.h> 22a10cf76eSAxel Dörfler #include <PopUpMenu.h> 23a10cf76eSAxel Dörfler #include <Screen.h> 24a10cf76eSAxel Dörfler #include <String.h> 25a10cf76eSAxel Dörfler #include <Window.h> 26a10cf76eSAxel Dörfler 27a10cf76eSAxel Dörfler #include <cstdio> 28a10cf76eSAxel Dörfler #include <cstdlib> 29a10cf76eSAxel Dörfler #include <cstring> 30a10cf76eSAxel Dörfler 31a10cf76eSAxel Dörfler #include "AlertWindow.h" 32a10cf76eSAxel Dörfler #include "Constants.h" 33a10cf76eSAxel Dörfler #include "RefreshWindow.h" 34a10cf76eSAxel Dörfler #include "MonitorView.h" 35a10cf76eSAxel Dörfler #include "ScreenSettings.h" 36a10cf76eSAxel Dörfler #include "ScreenWindow.h" 37a10cf76eSAxel Dörfler #include "Utility.h" 38a10cf76eSAxel Dörfler 39a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant. 40a10cf76eSAxel Dörfler * It's a solution that works with the current BeOS interface that Haiku 41a10cf76eSAxel Dörfler * adopted. 42a10cf76eSAxel Dörfler * However, it's not a nice and clean solution. Don't use this header in any 43a10cf76eSAxel Dörfler * application if you can avoid it. No other driver is using this, or should 44a10cf76eSAxel Dörfler * be using this. 45a10cf76eSAxel Dörfler * It will be replaced as soon as we introduce an updated accelerant interface 46a10cf76eSAxel Dörfler * which may even happen before R1 hits the streets. 47a10cf76eSAxel Dörfler */ 48a10cf76eSAxel Dörfler 49a10cf76eSAxel Dörfler #include "multimon.h" // the usual: DANGER WILL, ROBINSON! 50a10cf76eSAxel Dörfler 51a10cf76eSAxel Dörfler 52a10cf76eSAxel Dörfler #define USE_FIXED_REFRESH 53a10cf76eSAxel Dörfler // define to use fixed standard refresh rates 54a10cf76eSAxel Dörfler // undefine to get standard refresh rates from driver 55a10cf76eSAxel Dörfler 56a10cf76eSAxel Dörfler 57a10cf76eSAxel Dörfler // list of officially supported colour spaces 58a10cf76eSAxel Dörfler static const struct { 59a10cf76eSAxel Dörfler color_space space; 60a10cf76eSAxel Dörfler int32 bits_per_pixel; 61a10cf76eSAxel Dörfler const char* label; 62a10cf76eSAxel Dörfler } kColorSpaces[] = { 63a10cf76eSAxel Dörfler { B_CMAP8, 8, "8 Bits/Pixel, 256 Colors" }, 64a10cf76eSAxel Dörfler { B_RGB15, 15, "15 Bits/Pixel, 32768 Colors" }, 65a10cf76eSAxel Dörfler { B_RGB16, 16, "16 Bits/Pixel, 65536 Colors" }, 66a10cf76eSAxel Dörfler { B_RGB32, 32, "32 Bits/Pixel, 16 Million Colors" } 67a10cf76eSAxel Dörfler }; 68a10cf76eSAxel Dörfler static const int32 kColorSpaceCount = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]); 69a10cf76eSAxel Dörfler 70a10cf76eSAxel Dörfler // list of standard refresh rates 71a10cf76eSAxel Dörfler static const int32 kRefreshRates[] = {56, 60, 70, 72, 75}; 72a10cf76eSAxel Dörfler static const int32 kRefreshRateCount = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]); 73a10cf76eSAxel Dörfler 74a10cf76eSAxel Dörfler 75a10cf76eSAxel Dörfler // list of combine modes 76a10cf76eSAxel Dörfler static const struct { 77a10cf76eSAxel Dörfler combine_mode mode; 78a10cf76eSAxel Dörfler const char *name; 79a10cf76eSAxel Dörfler } kCombineModes[] = { 80a10cf76eSAxel Dörfler { kCombineDisable, "disable" }, 81a10cf76eSAxel Dörfler { kCombineHorizontally, "horizontally" }, 82a10cf76eSAxel Dörfler { kCombineVertically, "vertically" } 83a10cf76eSAxel Dörfler }; 84a10cf76eSAxel Dörfler static const int32 kCombineModeCount = sizeof(kCombineModes) / sizeof(kCombineModes[0]); 85a10cf76eSAxel Dörfler 86a10cf76eSAxel Dörfler 87a10cf76eSAxel Dörfler static BString 88a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode) 89a10cf76eSAxel Dörfler { 90a10cf76eSAxel Dörfler switch (mode) { 91a10cf76eSAxel Dörfler case 0: return "disabled"; 92a10cf76eSAxel Dörfler case 1: return "NTSC"; 93a10cf76eSAxel Dörfler case 2: return "NTSC Japan"; 94a10cf76eSAxel Dörfler case 3: return "PAL BDGHI"; 95a10cf76eSAxel Dörfler case 4: return "PAL M"; 96a10cf76eSAxel Dörfler case 5: return "PAL N"; 97a10cf76eSAxel Dörfler case 6: return "SECAM"; 98a10cf76eSAxel Dörfler case 101: return "NTSC 443"; 99a10cf76eSAxel Dörfler case 102: return "PAL 60"; 100a10cf76eSAxel Dörfler case 103: return "PAL NC"; 101a10cf76eSAxel Dörfler default: 102a10cf76eSAxel Dörfler { 103a10cf76eSAxel Dörfler BString name; 104a10cf76eSAxel Dörfler name << "??? (" << mode << ")"; 105a10cf76eSAxel Dörfler 106a10cf76eSAxel Dörfler return name; 107a10cf76eSAxel Dörfler } 108a10cf76eSAxel Dörfler } 109a10cf76eSAxel Dörfler } 110a10cf76eSAxel Dörfler 111a10cf76eSAxel Dörfler 112a10cf76eSAxel Dörfler static void 113a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string) 114a10cf76eSAxel Dörfler { 115a10cf76eSAxel Dörfler string << mode.width << " x " << mode.height; 116a10cf76eSAxel Dörfler } 117a10cf76eSAxel Dörfler 118a10cf76eSAxel Dörfler 119a10cf76eSAxel Dörfler static void 120a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string, 121a10cf76eSAxel Dörfler bool appendUnit = true, bool alwaysWithFraction = false) 122a10cf76eSAxel Dörfler { 123a10cf76eSAxel Dörfler snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, refresh); 124a10cf76eSAxel Dörfler string.UnlockBuffer(); 125a10cf76eSAxel Dörfler 126a10cf76eSAxel Dörfler if (appendUnit) 127a10cf76eSAxel Dörfler string << " Hz"; 128a10cf76eSAxel Dörfler } 129a10cf76eSAxel Dörfler 130a10cf76eSAxel Dörfler 13107184a9eSAxel Dörfler static const char* 13207184a9eSAxel Dörfler screen_errors(status_t status) 13307184a9eSAxel Dörfler { 13407184a9eSAxel Dörfler switch (status) { 13507184a9eSAxel Dörfler case B_ENTRY_NOT_FOUND: 13607184a9eSAxel Dörfler return "Unknown Mode"; 13707184a9eSAxel Dörfler // TODO: add more? 13807184a9eSAxel Dörfler 13907184a9eSAxel Dörfler default: 14007184a9eSAxel Dörfler return strerror(status); 14107184a9eSAxel Dörfler } 14207184a9eSAxel Dörfler } 14307184a9eSAxel Dörfler 14407184a9eSAxel Dörfler 145a10cf76eSAxel Dörfler // #pragma mark - 146a10cf76eSAxel Dörfler 147a10cf76eSAxel Dörfler 148*5a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings *settings) 149*5a78744bSAxel Dörfler : BWindow(settings->WindowFrame(), "Screen", B_TITLED_WINDOW, 150a10cf76eSAxel Dörfler B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES), 151a10cf76eSAxel Dörfler fScreenMode(this), 152a10cf76eSAxel Dörfler fChangingAllWorkspaces(false) 153a10cf76eSAxel Dörfler { 154a10cf76eSAxel Dörfler BScreen screen(this); 155a10cf76eSAxel Dörfler BRect frame(Bounds()); 156a10cf76eSAxel Dörfler 157a10cf76eSAxel Dörfler fScreenMode.Get(fOriginal); 158a10cf76eSAxel Dörfler fActive = fSelected = fOriginal; 159a10cf76eSAxel Dörfler 160a10cf76eSAxel Dörfler BView *view = new BView(frame, "ScreenView", B_FOLLOW_ALL, B_WILL_DRAW); 161a10cf76eSAxel Dörfler view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 162a10cf76eSAxel Dörfler AddChild(view); 163a10cf76eSAxel Dörfler 164*5a78744bSAxel Dörfler fSettings = settings; 165*5a78744bSAxel Dörfler 166*5a78744bSAxel Dörfler // we need the "Current Workspace" first to get its height 167*5a78744bSAxel Dörfler 168*5a78744bSAxel Dörfler BPopUpMenu *popUpMenu = new BPopUpMenu("Current Workspace", true, true); 169*5a78744bSAxel Dörfler fAllWorkspacesItem = new BMenuItem("All Workspaces", new BMessage(WORKSPACE_CHECK_MSG)); 170*5a78744bSAxel Dörfler popUpMenu->AddItem(fAllWorkspacesItem); 171*5a78744bSAxel Dörfler BMenuItem *item = new BMenuItem("Current Workspace", new BMessage(WORKSPACE_CHECK_MSG)); 172*5a78744bSAxel Dörfler item->SetMarked(true); 173*5a78744bSAxel Dörfler popUpMenu->AddItem(item); 174*5a78744bSAxel Dörfler 175*5a78744bSAxel Dörfler BMenuField* workspaceMenuField = new BMenuField(BRect(0, 0, 125, 18), 176*5a78744bSAxel Dörfler "WorkspaceMenu", NULL, popUpMenu, true); 177*5a78744bSAxel Dörfler workspaceMenuField->ResizeToPreferred(); 178a10cf76eSAxel Dörfler 179a10cf76eSAxel Dörfler // box on the left with workspace count and monitor view 180a10cf76eSAxel Dörfler 181*5a78744bSAxel Dörfler float labelWidth = be_plain_font->StringWidth("Workspaces count:") + 5.0f; 182a10cf76eSAxel Dörfler 183*5a78744bSAxel Dörfler BRect rect(10.0, 7.0 + workspaceMenuField->Bounds().Height() / 2.0f, 184*5a78744bSAxel Dörfler 26 + labelWidth + 32, 155.0); 185*5a78744bSAxel Dörfler BBox *screenBox = new BBox(rect, "left box"); 186a10cf76eSAxel Dörfler 187*5a78744bSAxel Dörfler rect = screenBox->Bounds().InsetByCopy(8, 8); 188*5a78744bSAxel Dörfler rect.bottom = rect.top + workspaceMenuField->Bounds().Height(); 189*5a78744bSAxel Dörfler popUpMenu = new BPopUpMenu("", true, true); 190*5a78744bSAxel Dörfler BMenuField *menuField = new BMenuField(rect, "WorkspaceCountMenu", 191*5a78744bSAxel Dörfler "Workspace count:", popUpMenu, true); 192*5a78744bSAxel Dörfler float width, height; 193*5a78744bSAxel Dörfler menuField->GetPreferredSize(&width, &height); 194*5a78744bSAxel Dörfler menuField->ResizeTo(rect.Width(), height); 195*5a78744bSAxel Dörfler menuField->MoveTo(rect.left, screenBox->Bounds().bottom - 8 - height); 196*5a78744bSAxel Dörfler menuField->SetDivider(labelWidth); 197a10cf76eSAxel Dörfler screenBox->AddChild(menuField); 198a10cf76eSAxel Dörfler 199a10cf76eSAxel Dörfler for (int32 count = 1; count <= 32; count++) { 200a10cf76eSAxel Dörfler BString workspaceCount; 201a10cf76eSAxel Dörfler workspaceCount << count; 202a10cf76eSAxel Dörfler 203a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_WORKSPACE_CHANGED_MSG); 204a10cf76eSAxel Dörfler message->AddInt32("workspace count", count); 205a10cf76eSAxel Dörfler 206a10cf76eSAxel Dörfler popUpMenu->AddItem(new BMenuItem(workspaceCount.String(), 207a10cf76eSAxel Dörfler message)); 208a10cf76eSAxel Dörfler } 209a10cf76eSAxel Dörfler 210*5a78744bSAxel Dörfler item = popUpMenu->ItemAt(count_workspaces() - 1); 211a10cf76eSAxel Dörfler if (item != NULL) 212a10cf76eSAxel Dörfler item->SetMarked(true); 213a10cf76eSAxel Dörfler 214*5a78744bSAxel Dörfler rect = screenBox->Bounds().InsetByCopy(22, 22); 215*5a78744bSAxel Dörfler fMonitorView = new MonitorView(rect, "monitor", 216*5a78744bSAxel Dörfler screen.Frame().Width() + 1, screen.Frame().Height() + 1); 217*5a78744bSAxel Dörfler screenBox->AddChild(fMonitorView); 218*5a78744bSAxel Dörfler 219a10cf76eSAxel Dörfler view->AddChild(screenBox); 220a10cf76eSAxel Dörfler 221a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 222a10cf76eSAxel Dörfler 223*5a78744bSAxel Dörfler rect = screenBox->Frame(); 224*5a78744bSAxel Dörfler rect.top = 7.0f; 225*5a78744bSAxel Dörfler rect.left = rect.right + 10.0f; 226*5a78744bSAxel Dörfler rect.right = rect.left + 190.0f; 227a10cf76eSAxel Dörfler BBox* controlsBox = new BBox(rect); 228*5a78744bSAxel Dörfler controlsBox->SetLabel(workspaceMenuField); 229a10cf76eSAxel Dörfler 230*5a78744bSAxel Dörfler rect.SetLeftTop(controlsBox->Bounds().RightBottom()); 231a10cf76eSAxel Dörfler fApplyButton = new BButton(rect, "ApplyButton", "Apply", 232*5a78744bSAxel Dörfler new BMessage(BUTTON_APPLY_MSG), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 233a10cf76eSAxel Dörfler fApplyButton->ResizeToPreferred(); 234*5a78744bSAxel Dörfler fApplyButton->MoveTo(rect.LeftTop() - BPoint(8, 8) 235*5a78744bSAxel Dörfler - fApplyButton->Bounds().RightBottom()); 236a10cf76eSAxel Dörfler fApplyButton->SetEnabled(false); 237a10cf76eSAxel Dörfler controlsBox->AddChild(fApplyButton); 238a10cf76eSAxel Dörfler 239*5a78744bSAxel Dörfler labelWidth = controlsBox->StringWidth("Refresh rate:") + 5.0f; 240a10cf76eSAxel Dörfler fResolutionMenu = new BPopUpMenu("resolution", true, true); 241a10cf76eSAxel Dörfler 242a10cf76eSAxel Dörfler uint16 previousWidth = 0, previousHeight = 0; 243a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 244a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 245a10cf76eSAxel Dörfler 246a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 247a10cf76eSAxel Dörfler continue; 248a10cf76eSAxel Dörfler 249a10cf76eSAxel Dörfler previousWidth = mode.width; 250a10cf76eSAxel Dörfler previousHeight = mode.height; 251a10cf76eSAxel Dörfler 252a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_RESOLUTION_MSG); 253a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 254a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 255a10cf76eSAxel Dörfler 256a10cf76eSAxel Dörfler BString name; 257a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 258a10cf76eSAxel Dörfler 259a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 260a10cf76eSAxel Dörfler } 261a10cf76eSAxel Dörfler 262*5a78744bSAxel Dörfler rect.Set(10.0, 30.0, 179.0, 48.0); 263a10cf76eSAxel Dörfler fResolutionField = new BMenuField(rect, "ResolutionMenu", "Resolution:", 264a10cf76eSAxel Dörfler fResolutionMenu, true); 265*5a78744bSAxel Dörfler fResolutionField->SetAlignment(B_ALIGN_RIGHT); 266*5a78744bSAxel Dörfler fResolutionField->SetDivider(labelWidth); 267a10cf76eSAxel Dörfler controlsBox->AddChild(fResolutionField); 268a10cf76eSAxel Dörfler 269a10cf76eSAxel Dörfler fColorsMenu = new BPopUpMenu("colors", true, true); 270a10cf76eSAxel Dörfler 271a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 272a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_COLORS_MSG); 273a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 274a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 275a10cf76eSAxel Dörfler 276a10cf76eSAxel Dörfler fColorsMenu->AddItem(new BMenuItem(kColorSpaces[i].label, message)); 277a10cf76eSAxel Dörfler } 278a10cf76eSAxel Dörfler 279*5a78744bSAxel Dörfler rect.Set(10.0, 58.0, 179.0, 76.0); 280a10cf76eSAxel Dörfler fColorsField = new BMenuField(rect, "ColorsMenu", "Colors:", fColorsMenu, true); 281*5a78744bSAxel Dörfler fColorsField->SetAlignment(B_ALIGN_RIGHT); 282*5a78744bSAxel Dörfler fColorsField->SetDivider(labelWidth); 283a10cf76eSAxel Dörfler controlsBox->AddChild(fColorsField); 284a10cf76eSAxel Dörfler 285a10cf76eSAxel Dörfler fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 286a10cf76eSAxel Dörfler 287a10cf76eSAxel Dörfler #ifdef USE_FIXED_REFRESH 288a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 289a10cf76eSAxel Dörfler BString name; 290a10cf76eSAxel Dörfler name << kRefreshRates[i] << " Hz"; 291a10cf76eSAxel Dörfler 292a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_REFRESH_MSG); 293a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 294a10cf76eSAxel Dörfler 295a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 296a10cf76eSAxel Dörfler } 297a10cf76eSAxel Dörfler #endif 298a10cf76eSAxel Dörfler 299a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_OTHER_REFRESH_MSG); 300a10cf76eSAxel Dörfler 301a10cf76eSAxel Dörfler fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message); 302a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 303a10cf76eSAxel Dörfler 304*5a78744bSAxel Dörfler rect.Set(10.0, 86.0, 179.0, 104.0); 305a10cf76eSAxel Dörfler fRefreshField = new BMenuField(rect, "RefreshMenu", "Refresh Rate:", fRefreshMenu, true); 306*5a78744bSAxel Dörfler fRefreshField->SetAlignment(B_ALIGN_RIGHT); 307*5a78744bSAxel Dörfler fRefreshField->SetDivider(labelWidth); 308a10cf76eSAxel Dörfler controlsBox->AddChild(fRefreshField); 309a10cf76eSAxel Dörfler 310a10cf76eSAxel Dörfler view->AddChild(controlsBox); 311a10cf76eSAxel Dörfler 312a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 313a10cf76eSAxel Dörfler { 314a10cf76eSAxel Dörfler bool dummy; 315a10cf76eSAxel Dörfler uint32 dummy32; 316a10cf76eSAxel Dörfler bool multiMonSupport; 317a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 318a10cf76eSAxel Dörfler bool tvStandardSupport; 319a10cf76eSAxel Dörfler 320a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 321a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 322a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 323a10cf76eSAxel Dörfler 324a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 325a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 326*5a78744bSAxel Dörfler if (multiMonSupport) 327a10cf76eSAxel Dörfler controlsBox->ResizeTo(366, 148); 328a10cf76eSAxel Dörfler 329a10cf76eSAxel Dörfler fCombineMenu = new BPopUpMenu("CombineDisplays", true, true); 330a10cf76eSAxel Dörfler 331a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 332a10cf76eSAxel Dörfler message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 333a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 334a10cf76eSAxel Dörfler 335a10cf76eSAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, message)); 336a10cf76eSAxel Dörfler } 337a10cf76eSAxel Dörfler 338a10cf76eSAxel Dörfler rect.Set(185, 30, 356, 48); 339a10cf76eSAxel Dörfler BMenuField* menuField = new BMenuField(rect, "CombineMenu", 340a10cf76eSAxel Dörfler "Combine Displays:", fCombineMenu, true); 341a10cf76eSAxel Dörfler menuField->SetDivider(90); 342a10cf76eSAxel Dörfler controlsBox->AddChild(menuField); 343a10cf76eSAxel Dörfler 344a10cf76eSAxel Dörfler if (!multiMonSupport) 345a10cf76eSAxel Dörfler menuField->Hide(); 346a10cf76eSAxel Dörfler 347a10cf76eSAxel Dörfler fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true); 348a10cf76eSAxel Dörfler 349a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 350a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 351a10cf76eSAxel Dörfler message->AddBool("swap", false); 352a10cf76eSAxel Dörfler fSwapDisplaysMenu->AddItem(new BMenuItem("no", message)); 353a10cf76eSAxel Dörfler 354a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 355a10cf76eSAxel Dörfler message->AddBool("swap", true); 356a10cf76eSAxel Dörfler fSwapDisplaysMenu->AddItem(new BMenuItem("yes", message)); 357a10cf76eSAxel Dörfler 358a10cf76eSAxel Dörfler rect.Set(199, 58, 356, 76); 359a10cf76eSAxel Dörfler menuField = new BMenuField(rect, "SwapMenu", "Swap Displays:", 360a10cf76eSAxel Dörfler fSwapDisplaysMenu, true); 361a10cf76eSAxel Dörfler menuField->SetDivider(76); 362a10cf76eSAxel Dörfler 363a10cf76eSAxel Dörfler controlsBox->AddChild(menuField); 364a10cf76eSAxel Dörfler if (!multiMonSupport) 365a10cf76eSAxel Dörfler menuField->Hide(); 366a10cf76eSAxel Dörfler 367a10cf76eSAxel Dörfler fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true); 368a10cf76eSAxel Dörfler 369a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 370a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 371a10cf76eSAxel Dörfler message->AddBool("use", false); 372a10cf76eSAxel Dörfler fUseLaptopPanelMenu->AddItem(new BMenuItem("if needed", message)); 373a10cf76eSAxel Dörfler 374a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 375a10cf76eSAxel Dörfler message->AddBool("use", true); 376a10cf76eSAxel Dörfler fUseLaptopPanelMenu->AddItem(new BMenuItem("always", message)); 377a10cf76eSAxel Dörfler 378a10cf76eSAxel Dörfler rect.Set(184, 86, 356, 104); 379a10cf76eSAxel Dörfler menuField = new BMenuField(rect, "UseLaptopPanel", "Use Laptop Panel:", 380a10cf76eSAxel Dörfler fUseLaptopPanelMenu, true); 381a10cf76eSAxel Dörfler menuField->SetDivider(91); 382a10cf76eSAxel Dörfler 383a10cf76eSAxel Dörfler controlsBox->AddChild(menuField); 384a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 385a10cf76eSAxel Dörfler menuField->Hide(); 386a10cf76eSAxel Dörfler 387a10cf76eSAxel Dörfler fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 388a10cf76eSAxel Dörfler 389a10cf76eSAxel Dörfler // arbitrary limit 390a10cf76eSAxel Dörfler uint32 i; 391a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 392a10cf76eSAxel Dörfler uint32 mode; 393a10cf76eSAxel Dörfler 394a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 395a10cf76eSAxel Dörfler break; 396a10cf76eSAxel Dörfler 397a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 398a10cf76eSAxel Dörfler 399a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 400a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 401a10cf76eSAxel Dörfler 402a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 403a10cf76eSAxel Dörfler } 404a10cf76eSAxel Dörfler 405a10cf76eSAxel Dörfler rect.Set(15, 114, 171, 132); 406a10cf76eSAxel Dörfler menuField = new BMenuField(rect, "tv standard", "Video Format:", 407a10cf76eSAxel Dörfler fTVStandardMenu, true); 408a10cf76eSAxel Dörfler menuField->SetDivider(73); 409a10cf76eSAxel Dörfler 410a10cf76eSAxel Dörfler if (!tvStandardSupport || i == 0) 411a10cf76eSAxel Dörfler menuField->Hide(); 412a10cf76eSAxel Dörfler 413a10cf76eSAxel Dörfler controlsBox->AddChild(menuField); 414a10cf76eSAxel Dörfler } 415a10cf76eSAxel Dörfler 416*5a78744bSAxel Dörfler rect.Set(10.0, screenBox->Frame().bottom + 10.0, 100.0, 200.0); 417a10cf76eSAxel Dörfler fDefaultsButton = new BButton(rect, "DefaultsButton", "Defaults", 418a10cf76eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG)); 419a10cf76eSAxel Dörfler fDefaultsButton->ResizeToPreferred(); 420a10cf76eSAxel Dörfler view->AddChild(fDefaultsButton); 421a10cf76eSAxel Dörfler 422*5a78744bSAxel Dörfler rect.OffsetBy(fDefaultsButton->Bounds().Width() + 10, 0); 423a10cf76eSAxel Dörfler fRevertButton = new BButton(rect, "RevertButton", "Revert", 424a10cf76eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 425a10cf76eSAxel Dörfler fRevertButton->ResizeToPreferred(); 426a10cf76eSAxel Dörfler fRevertButton->SetEnabled(false); 427a10cf76eSAxel Dörfler view->AddChild(fRevertButton); 428a10cf76eSAxel Dörfler 429*5a78744bSAxel Dörfler ResizeTo(controlsBox->Frame().right + 10, 430*5a78744bSAxel Dörfler fDefaultsButton->Frame().bottom + 10); 431*5a78744bSAxel Dörfler 432a10cf76eSAxel Dörfler UpdateControls(); 433a10cf76eSAxel Dörfler } 434a10cf76eSAxel Dörfler 435a10cf76eSAxel Dörfler 436a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 437a10cf76eSAxel Dörfler { 438a10cf76eSAxel Dörfler delete fSettings; 439a10cf76eSAxel Dörfler } 440a10cf76eSAxel Dörfler 441a10cf76eSAxel Dörfler 442a10cf76eSAxel Dörfler bool 443a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 444a10cf76eSAxel Dörfler { 445a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 446a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 447a10cf76eSAxel Dörfler 448a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 449a10cf76eSAxel Dörfler } 450a10cf76eSAxel Dörfler 451a10cf76eSAxel Dörfler 452a10cf76eSAxel Dörfler /** update resolution list according to combine mode 453a10cf76eSAxel Dörfler * (some resolution may not be combinable due to memory restrictions) 454a10cf76eSAxel Dörfler */ 455a10cf76eSAxel Dörfler 456a10cf76eSAxel Dörfler void 457a10cf76eSAxel Dörfler ScreenWindow::CheckResolutionMenu() 458a10cf76eSAxel Dörfler { 459a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 460a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 461a10cf76eSAxel Dörfler 462a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 463a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 464a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 465a10cf76eSAxel Dörfler continue; 466a10cf76eSAxel Dörfler 467a10cf76eSAxel Dörfler BString name; 468a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 469a10cf76eSAxel Dörfler 470a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 471a10cf76eSAxel Dörfler if (item != NULL) 472a10cf76eSAxel Dörfler item->SetEnabled(true); 473a10cf76eSAxel Dörfler } 474a10cf76eSAxel Dörfler } 475a10cf76eSAxel Dörfler 476a10cf76eSAxel Dörfler 477a10cf76eSAxel Dörfler /** update color and refresh options according to current mode 478a10cf76eSAxel Dörfler * (a color space is made active if there is any mode with 479a10cf76eSAxel Dörfler * given resolution and this colour space; same applies for 480a10cf76eSAxel Dörfler * refresh rate, though "Other…" is always possible) 481a10cf76eSAxel Dörfler */ 482a10cf76eSAxel Dörfler 483a10cf76eSAxel Dörfler void 484a10cf76eSAxel Dörfler ScreenWindow::CheckColorMenu() 485a10cf76eSAxel Dörfler { 486a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 487a10cf76eSAxel Dörfler bool supported = false; 488a10cf76eSAxel Dörfler 489a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 490a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 491a10cf76eSAxel Dörfler 492a10cf76eSAxel Dörfler if (fSelected.width == mode.width 493a10cf76eSAxel Dörfler && fSelected.height == mode.height 494a10cf76eSAxel Dörfler && kColorSpaces[i].space == mode.space 495a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 496a10cf76eSAxel Dörfler supported = true; 497a10cf76eSAxel Dörfler break; 498a10cf76eSAxel Dörfler } 499a10cf76eSAxel Dörfler } 500a10cf76eSAxel Dörfler 501a10cf76eSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(i); 502a10cf76eSAxel Dörfler if (item) 503a10cf76eSAxel Dörfler item->SetEnabled(supported); 504a10cf76eSAxel Dörfler } 505a10cf76eSAxel Dörfler } 506a10cf76eSAxel Dörfler 507a10cf76eSAxel Dörfler 508a10cf76eSAxel Dörfler /** Enable/disable refresh options according to current mode. 509a10cf76eSAxel Dörfler * Only needed when USE_FIXED_REFRESH is not defined. 510a10cf76eSAxel Dörfler */ 511a10cf76eSAxel Dörfler 512a10cf76eSAxel Dörfler void 513a10cf76eSAxel Dörfler ScreenWindow::CheckRefreshMenu() 514a10cf76eSAxel Dörfler { 515a10cf76eSAxel Dörfler #ifndef USE_FIXED_REFRESH 516a10cf76eSAxel Dörfler // ToDo: does currently not compile! 517a10cf76eSAxel Dörfler for (int32 i = fRefreshMenu->CountItems() - 2; i >= 0; --i) { 518a10cf76eSAxel Dörfler delete fRefreshMenu->RemoveItem(i); 519a10cf76eSAxel Dörfler } 520a10cf76eSAxel Dörfler 521a10cf76eSAxel Dörfler for (int32 i = 0; i < fModeListCount; ++i) { 522a10cf76eSAxel Dörfler if (virtualWidth == fModeList[i].virtual_width 523a10cf76eSAxel Dörfler && virtualHeight == fModeList[i].virtual_height 524a10cf76eSAxel Dörfler && combine == get_combine_mode(&fModeList[i])) { 525a10cf76eSAxel Dörfler BString name; 526a10cf76eSAxel Dörfler BMenuItem *item; 527a10cf76eSAxel Dörfler 528a10cf76eSAxel Dörfler int32 refresh10 = get_refresh10(fModeList[i]); 529a10cf76eSAxel Dörfler refresh10_to_string(name, refresh10); 530a10cf76eSAxel Dörfler 531a10cf76eSAxel Dörfler item = fRefreshMenu->FindItem(name.String()); 532a10cf76eSAxel Dörfler if (item == NULL) { 533a10cf76eSAxel Dörfler BMessage *msg = new BMessage(POP_REFRESH_MSG); 534a10cf76eSAxel Dörfler msg->AddFloat("refresh", refresh); 535a10cf76eSAxel Dörfler 536a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), msg), 537a10cf76eSAxel Dörfler fRefreshMenu->CountItems() - 1); 538a10cf76eSAxel Dörfler } 539a10cf76eSAxel Dörfler } 540a10cf76eSAxel Dörfler } 541a10cf76eSAxel Dörfler #endif 542a10cf76eSAxel Dörfler 543a10cf76eSAxel Dörfler // TBD: some drivers lack many refresh rates; still, they 544a10cf76eSAxel Dörfler // can be used by generating the mode manually 545a10cf76eSAxel Dörfler /* 546a10cf76eSAxel Dörfler for( i = 0; i < sizeof( refresh_list ) / sizeof( refresh_list[0] ); ++i ) { 547a10cf76eSAxel Dörfler BMenuItem *item; 548a10cf76eSAxel Dörfler bool supported = false; 549a10cf76eSAxel Dörfler 550a10cf76eSAxel Dörfler for( j = 0; j < fModeListCount; ++j ) { 551a10cf76eSAxel Dörfler if( width == fModeList[j].virtual_width && 552a10cf76eSAxel Dörfler height == fModeList[j].virtual_height && 553a10cf76eSAxel Dörfler refresh_list[i].refresh * 10 == getModeRefresh10( &fModeList[j] )) 554a10cf76eSAxel Dörfler { 555a10cf76eSAxel Dörfler supported = true; 556a10cf76eSAxel Dörfler break; 557a10cf76eSAxel Dörfler } 558a10cf76eSAxel Dörfler } 559a10cf76eSAxel Dörfler 560a10cf76eSAxel Dörfler item = fRefreshMenu->ItemAt( i ); 561a10cf76eSAxel Dörfler if( item ) 562a10cf76eSAxel Dörfler item->SetEnabled( supported ); 563a10cf76eSAxel Dörfler } 564a10cf76eSAxel Dörfler */ 565a10cf76eSAxel Dörfler } 566a10cf76eSAxel Dörfler 567a10cf76eSAxel Dörfler 568a10cf76eSAxel Dörfler /** activate appropriate menu item according to selected refresh rate */ 569a10cf76eSAxel Dörfler 570a10cf76eSAxel Dörfler void 571a10cf76eSAxel Dörfler ScreenWindow::UpdateRefreshControl() 572a10cf76eSAxel Dörfler { 573a10cf76eSAxel Dörfler BString string; 574a10cf76eSAxel Dörfler refresh_rate_to_string(fSelected.refresh, string); 575a10cf76eSAxel Dörfler 576a10cf76eSAxel Dörfler BMenuItem* item = fRefreshMenu->FindItem(string.String()); 577a10cf76eSAxel Dörfler if (item) { 578a10cf76eSAxel Dörfler if (!item->IsMarked()) 579a10cf76eSAxel Dörfler item->SetMarked(true); 580a10cf76eSAxel Dörfler // "Other…" items only contains a refresh rate when active 581a10cf76eSAxel Dörfler fOtherRefresh->SetLabel("Other…"); 582a10cf76eSAxel Dörfler return; 583a10cf76eSAxel Dörfler } 584a10cf76eSAxel Dörfler 585a10cf76eSAxel Dörfler // this is a non-standard refresh rate 586a10cf76eSAxel Dörfler 587a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 588a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 589a10cf76eSAxel Dörfler 590a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 591a10cf76eSAxel Dörfler 592a10cf76eSAxel Dörfler string.Append("/Other" B_UTF8_ELLIPSIS); 593a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 594a10cf76eSAxel Dörfler } 595a10cf76eSAxel Dörfler 596a10cf76eSAxel Dörfler 597a10cf76eSAxel Dörfler void 598a10cf76eSAxel Dörfler ScreenWindow::UpdateMonitorView() 599a10cf76eSAxel Dörfler { 600a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 601a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 602a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 603a10cf76eSAxel Dörfler 604a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 605a10cf76eSAxel Dörfler } 606a10cf76eSAxel Dörfler 607a10cf76eSAxel Dörfler 608a10cf76eSAxel Dörfler void 609a10cf76eSAxel Dörfler ScreenWindow::UpdateControls() 610a10cf76eSAxel Dörfler { 611a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 612a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 613a10cf76eSAxel Dörfler item->SetMarked(true); 614a10cf76eSAxel Dörfler 615a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 616a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 617a10cf76eSAxel Dörfler item->SetMarked(true); 618a10cf76eSAxel Dörfler 619a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 620a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 621a10cf76eSAxel Dörfler 622a10cf76eSAxel Dörfler uint32 tvStandard; 623a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 624a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 625a10cf76eSAxel Dörfler if (!item->IsMarked()) 626a10cf76eSAxel Dörfler item->SetMarked(true); 627a10cf76eSAxel Dörfler break; 628a10cf76eSAxel Dörfler } 629a10cf76eSAxel Dörfler } 630a10cf76eSAxel Dörfler 631a10cf76eSAxel Dörfler CheckResolutionMenu(); 632a10cf76eSAxel Dörfler CheckColorMenu(); 633a10cf76eSAxel Dörfler CheckRefreshMenu(); 634a10cf76eSAxel Dörfler 635a10cf76eSAxel Dörfler BString string; 636a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 637a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 638a10cf76eSAxel Dörfler 639a10cf76eSAxel Dörfler if (item != NULL) { 640a10cf76eSAxel Dörfler if (!item->IsMarked()) 641a10cf76eSAxel Dörfler item->SetMarked(true); 642a10cf76eSAxel Dörfler } else { 643a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 644a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 645a10cf76eSAxel Dörfler // 1. add a new resolution to list 646a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 647a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 648a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 649a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 650a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 651a10cf76eSAxel Dörfler // 2. choose nearest resolution 652a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 653a10cf76eSAxel Dörfler // 3. choose lowest resolution 654a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 655a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 656a10cf76eSAxel Dörfler if (item) 657a10cf76eSAxel Dörfler item->SetMarked(true); 658a10cf76eSAxel Dörfler 659a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 660a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 661a10cf76eSAxel Dörfler } 662a10cf76eSAxel Dörfler 663a10cf76eSAxel Dörfler // mark active combine mode 664a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 665a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 666a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 667a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 668a10cf76eSAxel Dörfler item->SetMarked(true); 669a10cf76eSAxel Dörfler break; 670a10cf76eSAxel Dörfler } 671a10cf76eSAxel Dörfler } 672a10cf76eSAxel Dörfler 673a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 674a10cf76eSAxel Dörfler 675a10cf76eSAxel Dörfler for (int32 i = kColorSpaceCount; i-- > 0;) { 676a10cf76eSAxel Dörfler if (kColorSpaces[i].space == fSelected.space) { 677a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(i); 678a10cf76eSAxel Dörfler break; 679a10cf76eSAxel Dörfler } 680a10cf76eSAxel Dörfler } 681a10cf76eSAxel Dörfler 682a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 683a10cf76eSAxel Dörfler item->SetMarked(true); 684a10cf76eSAxel Dörfler 685a10cf76eSAxel Dörfler string.Truncate(0); 686a10cf76eSAxel Dörfler string << fSelected.BitsPerPixel() << " Bits/Pixel"; 687a10cf76eSAxel Dörfler if (string != fColorsMenu->Superitem()->Label()) 688a10cf76eSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 689a10cf76eSAxel Dörfler 690a10cf76eSAxel Dörfler UpdateMonitorView(); 691a10cf76eSAxel Dörfler UpdateRefreshControl(); 692a10cf76eSAxel Dörfler 693a10cf76eSAxel Dörfler CheckApplyEnabled(); 694a10cf76eSAxel Dörfler } 695a10cf76eSAxel Dörfler 696a10cf76eSAxel Dörfler 697a10cf76eSAxel Dörfler /** reflect active mode in chosen settings */ 698a10cf76eSAxel Dörfler 699a10cf76eSAxel Dörfler void 700a10cf76eSAxel Dörfler ScreenWindow::UpdateActiveMode() 701a10cf76eSAxel Dörfler { 702a10cf76eSAxel Dörfler // usually, this function gets called after a mode 703a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 704a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 705a10cf76eSAxel Dörfler // what kind of mode we actually got 706a10cf76eSAxel Dörfler fScreenMode.Get(fActive); 707a10cf76eSAxel Dörfler fSelected = fActive; 708a10cf76eSAxel Dörfler 709a10cf76eSAxel Dörfler UpdateControls(); 710a10cf76eSAxel Dörfler } 711a10cf76eSAxel Dörfler 712a10cf76eSAxel Dörfler 713a10cf76eSAxel Dörfler void 714a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 715a10cf76eSAxel Dörfler { 716a10cf76eSAxel Dörfler // move window on screen, if necessary 717a10cf76eSAxel Dörfler if (frame.right <= Frame().right 718a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 719a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 720a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 721a10cf76eSAxel Dörfler } 722a10cf76eSAxel Dörfler } 723a10cf76eSAxel Dörfler 724a10cf76eSAxel Dörfler 725a10cf76eSAxel Dörfler void 726a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 727a10cf76eSAxel Dörfler { 728a10cf76eSAxel Dörfler if (fChangingAllWorkspaces) { 729a10cf76eSAxel Dörfler // we're currently changing all workspaces, so there is no need 730a10cf76eSAxel Dörfler // to update the interface 731a10cf76eSAxel Dörfler return; 732a10cf76eSAxel Dörfler } 733a10cf76eSAxel Dörfler 734a10cf76eSAxel Dörfler fScreenMode.Get(fOriginal); 735a10cf76eSAxel Dörfler fScreenMode.UpdateOriginalMode(); 736a10cf76eSAxel Dörfler 737a10cf76eSAxel Dörfler // only override current settings if they have not been changed yet 738a10cf76eSAxel Dörfler if (fSelected == fActive) 739a10cf76eSAxel Dörfler UpdateActiveMode(); 740a10cf76eSAxel Dörfler 7416edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 7426edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 743a10cf76eSAxel Dörfler } 744a10cf76eSAxel Dörfler 745a10cf76eSAxel Dörfler 746a10cf76eSAxel Dörfler void 747a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 748a10cf76eSAxel Dörfler { 749a10cf76eSAxel Dörfler switch (message->what) { 750a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 751a10cf76eSAxel Dörfler CheckApplyEnabled(); 752a10cf76eSAxel Dörfler break; 753a10cf76eSAxel Dörfler 754a10cf76eSAxel Dörfler case POP_WORKSPACE_CHANGED_MSG: 755a10cf76eSAxel Dörfler { 756a10cf76eSAxel Dörfler int32 index; 757a10cf76eSAxel Dörfler if (message->FindInt32("index", &index) == B_OK) 758a10cf76eSAxel Dörfler set_workspace_count(index + 1); 759a10cf76eSAxel Dörfler break; 760a10cf76eSAxel Dörfler } 761a10cf76eSAxel Dörfler 762a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 763a10cf76eSAxel Dörfler { 764a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 765a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 766a10cf76eSAxel Dörfler 767a10cf76eSAxel Dörfler CheckColorMenu(); 768a10cf76eSAxel Dörfler CheckRefreshMenu(); 769a10cf76eSAxel Dörfler 770a10cf76eSAxel Dörfler UpdateMonitorView(); 771a10cf76eSAxel Dörfler UpdateRefreshControl(); 772a10cf76eSAxel Dörfler 773a10cf76eSAxel Dörfler CheckApplyEnabled(); 774a10cf76eSAxel Dörfler break; 775a10cf76eSAxel Dörfler } 776a10cf76eSAxel Dörfler 777a10cf76eSAxel Dörfler case POP_COLORS_MSG: 778a10cf76eSAxel Dörfler { 779a10cf76eSAxel Dörfler message->FindInt32("space", (int32 *)&fSelected.space); 780a10cf76eSAxel Dörfler 781a10cf76eSAxel Dörfler BString string; 782a10cf76eSAxel Dörfler string << fSelected.BitsPerPixel() << " Bits/Pixel"; 783a10cf76eSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 784a10cf76eSAxel Dörfler 785a10cf76eSAxel Dörfler CheckApplyEnabled(); 786a10cf76eSAxel Dörfler break; 787a10cf76eSAxel Dörfler } 788a10cf76eSAxel Dörfler 789a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 790a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 791a10cf76eSAxel Dörfler fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS); 792a10cf76eSAxel Dörfler // revert "Other…" label - it might have had a refresh rate prefix 793a10cf76eSAxel Dörfler 794a10cf76eSAxel Dörfler CheckApplyEnabled(); 795a10cf76eSAxel Dörfler break; 796a10cf76eSAxel Dörfler 797a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 798a10cf76eSAxel Dörfler { 799a10cf76eSAxel Dörfler // make sure menu shows something usefull 800a10cf76eSAxel Dörfler UpdateRefreshControl(); 801a10cf76eSAxel Dörfler 802a10cf76eSAxel Dörfler BRect frame(Frame()); 803a10cf76eSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow(BRect(frame.left + 201.0, 804a10cf76eSAxel Dörfler frame.top + 34.0, frame.left + 509.0, frame.top + 169.0), 805a10cf76eSAxel Dörfler int32(fSelected.refresh * 10)); 806a10cf76eSAxel Dörfler fRefreshWindow->Show(); 807a10cf76eSAxel Dörfler break; 808a10cf76eSAxel Dörfler } 809a10cf76eSAxel Dörfler 810a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 811a10cf76eSAxel Dörfler { 812a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 813a10cf76eSAxel Dörfler // select the refresh rate chosen 814a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 815a10cf76eSAxel Dörfler 816a10cf76eSAxel Dörfler UpdateRefreshControl(); 817a10cf76eSAxel Dörfler CheckApplyEnabled(); 818a10cf76eSAxel Dörfler break; 819a10cf76eSAxel Dörfler } 820a10cf76eSAxel Dörfler 821a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 822a10cf76eSAxel Dörfler { 823a10cf76eSAxel Dörfler // new combine mode has bee chosen 824a10cf76eSAxel Dörfler int32 mode; 825a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 826a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 827a10cf76eSAxel Dörfler 828a10cf76eSAxel Dörfler CheckResolutionMenu(); 829a10cf76eSAxel Dörfler CheckApplyEnabled(); 830a10cf76eSAxel Dörfler break; 831a10cf76eSAxel Dörfler } 832a10cf76eSAxel Dörfler 833a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 834a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 835a10cf76eSAxel Dörfler CheckApplyEnabled(); 836a10cf76eSAxel Dörfler break; 837a10cf76eSAxel Dörfler 838a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 839a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 840a10cf76eSAxel Dörfler CheckApplyEnabled(); 841a10cf76eSAxel Dörfler break; 842a10cf76eSAxel Dörfler 843a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 844a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 845a10cf76eSAxel Dörfler CheckApplyEnabled(); 846a10cf76eSAxel Dörfler break; 847a10cf76eSAxel Dörfler 848a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 849a10cf76eSAxel Dörfler { 850a10cf76eSAxel Dörfler fSelected.width = 640; 851a10cf76eSAxel Dörfler fSelected.height = 480; 852a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 853a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 854a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 855a10cf76eSAxel Dörfler fSelected.swap_displays = false; 856a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 857a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 858a10cf76eSAxel Dörfler 859a10cf76eSAxel Dörfler UpdateControls(); 860a10cf76eSAxel Dörfler break; 861a10cf76eSAxel Dörfler } 862a10cf76eSAxel Dörfler 863a10cf76eSAxel Dörfler case BUTTON_REVERT_MSG: 864a10cf76eSAxel Dörfler case SET_INITIAL_MODE_MSG: 865a10cf76eSAxel Dörfler fScreenMode.Revert(); 866a10cf76eSAxel Dörfler UpdateActiveMode(); 867a10cf76eSAxel Dörfler break; 868a10cf76eSAxel Dörfler 869a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 870a10cf76eSAxel Dörfler Apply(); 871a10cf76eSAxel Dörfler break; 872a10cf76eSAxel Dörfler 873a10cf76eSAxel Dörfler case MAKE_INITIAL_MSG: { 874a10cf76eSAxel Dörfler // user pressed "keep" in confirmation box; 875a10cf76eSAxel Dörfler // select this mode in dialog and mark it as 876a10cf76eSAxel Dörfler // previous mode; if "all workspaces" is selected, 877a10cf76eSAxel Dörfler // distribute mode to all workspaces 878a10cf76eSAxel Dörfler 879a10cf76eSAxel Dörfler // use the mode that has eventually been set and 880a10cf76eSAxel Dörfler // thus we know to be working; it can differ from 881a10cf76eSAxel Dörfler // the mode selected by user due to hardware limitation 882a10cf76eSAxel Dörfler display_mode newMode; 883a10cf76eSAxel Dörfler BScreen screen(this); 884a10cf76eSAxel Dörfler screen.GetMode(&newMode); 885a10cf76eSAxel Dörfler 886a10cf76eSAxel Dörfler if (fAllWorkspacesItem->IsMarked()) { 887a10cf76eSAxel Dörfler int32 originatingWorkspace; 888a10cf76eSAxel Dörfler 889a10cf76eSAxel Dörfler // the original panel activates each workspace in turn; 890a10cf76eSAxel Dörfler // this is disguisting and there is a SetMode 891a10cf76eSAxel Dörfler // variant that accepts a workspace id, so let's take 892a10cf76eSAxel Dörfler // this one 893a10cf76eSAxel Dörfler originatingWorkspace = current_workspace(); 894a10cf76eSAxel Dörfler 895a10cf76eSAxel Dörfler // well, this "cannot be reverted" message is not 896a10cf76eSAxel Dörfler // entirely true - at least, you can revert it 897a10cf76eSAxel Dörfler // for current workspace; to not overwrite original 898a10cf76eSAxel Dörfler // mode during workspace switch, we use this flag 899a10cf76eSAxel Dörfler fChangingAllWorkspaces = true; 900a10cf76eSAxel Dörfler 901a10cf76eSAxel Dörfler for (int32 i = 0; i < count_workspaces(); i++) { 902a10cf76eSAxel Dörfler if (i != originatingWorkspace) 903a10cf76eSAxel Dörfler screen.SetMode(i, &newMode, true); 904a10cf76eSAxel Dörfler } 905a10cf76eSAxel Dörfler 906a10cf76eSAxel Dörfler fChangingAllWorkspaces = false; 907a10cf76eSAxel Dörfler } 908a10cf76eSAxel Dörfler 909a10cf76eSAxel Dörfler UpdateActiveMode(); 910a10cf76eSAxel Dörfler break; 911a10cf76eSAxel Dörfler } 912a10cf76eSAxel Dörfler 913a10cf76eSAxel Dörfler default: 914a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 915a10cf76eSAxel Dörfler break; 916a10cf76eSAxel Dörfler } 917a10cf76eSAxel Dörfler } 918a10cf76eSAxel Dörfler 919a10cf76eSAxel Dörfler 920a10cf76eSAxel Dörfler bool 921a10cf76eSAxel Dörfler ScreenWindow::CanApply() const 922a10cf76eSAxel Dörfler { 923a10cf76eSAxel Dörfler if (fAllWorkspacesItem->IsMarked()) 924a10cf76eSAxel Dörfler return true; 925a10cf76eSAxel Dörfler 926a10cf76eSAxel Dörfler return fSelected != fActive; 927a10cf76eSAxel Dörfler } 928a10cf76eSAxel Dörfler 929a10cf76eSAxel Dörfler 930a10cf76eSAxel Dörfler bool 931a10cf76eSAxel Dörfler ScreenWindow::CanRevert() const 932a10cf76eSAxel Dörfler { 933a10cf76eSAxel Dörfler if (fActive != fOriginal) 934a10cf76eSAxel Dörfler return true; 935a10cf76eSAxel Dörfler 936a10cf76eSAxel Dörfler return CanApply(); 937a10cf76eSAxel Dörfler } 938a10cf76eSAxel Dörfler 939a10cf76eSAxel Dörfler 940a10cf76eSAxel Dörfler void 941a10cf76eSAxel Dörfler ScreenWindow::CheckApplyEnabled() 942a10cf76eSAxel Dörfler { 943a10cf76eSAxel Dörfler fApplyButton->SetEnabled(CanApply()); 944a10cf76eSAxel Dörfler fRevertButton->SetEnabled(CanRevert()); 945a10cf76eSAxel Dörfler } 946a10cf76eSAxel Dörfler 947a10cf76eSAxel Dörfler 948a10cf76eSAxel Dörfler void 949a10cf76eSAxel Dörfler ScreenWindow::Apply() 950a10cf76eSAxel Dörfler { 951a10cf76eSAxel Dörfler if (fAllWorkspacesItem->IsMarked()) { 952a10cf76eSAxel Dörfler BAlert *workspacesAlert = new BAlert("WorkspacesAlert", 953a10cf76eSAxel Dörfler "Change all workspaces? This action cannot be reverted.", "Okay", "Cancel", 954a10cf76eSAxel Dörfler NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 955a10cf76eSAxel Dörfler 956a10cf76eSAxel Dörfler if (workspacesAlert->Go() == 1) 957a10cf76eSAxel Dörfler return; 958a10cf76eSAxel Dörfler } 959a10cf76eSAxel Dörfler 96007184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 96107184a9eSAxel Dörfler if (status == B_OK) { 962a10cf76eSAxel Dörfler fActive = fSelected; 963a10cf76eSAxel Dörfler 964a10cf76eSAxel Dörfler // ToDo: only show alert when this is an unknown mode 965a10cf76eSAxel Dörfler BWindow* window = new AlertWindow(this); 966a10cf76eSAxel Dörfler window->Show(); 96707184a9eSAxel Dörfler } else { 96807184a9eSAxel Dörfler char message[256]; 96907184a9eSAxel Dörfler snprintf(message, sizeof(message), 97007184a9eSAxel Dörfler "The screen mode could not be set:\n\t%s\n", screen_errors(status)); 97107184a9eSAxel Dörfler BAlert* alert = new BAlert("Screen Alert", message, "Okay", NULL, NULL, 97207184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 97307184a9eSAxel Dörfler alert->Go(); 974a10cf76eSAxel Dörfler } 97507184a9eSAxel Dörfler } 97607184a9eSAxel Dörfler 977