Fix FreeBSD build.
[haiku.git] / src / preferences / keymap / ModifierKeysWindow.cpp
blob621f50c24c835f4c2130101cfe73b6dccbe75582
1 /*
2 * Copyright 2011-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * John Scipione, jscipione@gmail.com
7 */
10 #include "ModifierKeysWindow.h"
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
16 #include <Bitmap.h>
17 #include <Button.h>
18 #include <Catalog.h>
19 #include <CheckBox.h>
20 #include <FindDirectory.h>
21 #include <IconUtils.h>
22 #include <InterfaceDefs.h>
23 #include <LayoutBuilder.h>
24 #include <Locale.h>
25 #include <MenuField.h>
26 #include <MenuItem.h>
27 #include <Message.h>
28 #include <Path.h>
29 #include <PopUpMenu.h>
30 #include <Resources.h>
31 #include <SeparatorView.h>
32 #include <Size.h>
33 #include <StringView.h>
35 #include "KeymapApplication.h"
38 #ifdef DEBUG_ALERT
39 # define FTRACE(x) fprintf(x)
40 #else
41 # define FTRACE(x) /* nothing */
42 #endif
45 enum {
46 SHIFT_KEY = 0x00000001,
47 CONTROL_KEY = 0x00000002,
48 OPTION_KEY = 0x00000004,
49 COMMAND_KEY = 0x00000008
52 enum {
53 MENU_ITEM_SHIFT = 0,
54 MENU_ITEM_CONTROL,
55 MENU_ITEM_OPTION,
56 MENU_ITEM_COMMAND,
57 MENU_ITEM_SEPERATOR,
58 MENU_ITEM_DISABLED
62 static const uint32 kMsgHideShowIcons = 'icon';
63 static const uint32 kMsgUpdateModifier = 'upmd';
64 static const uint32 kMsgApplyModifiers = 'apmd';
65 static const uint32 kMsgRevertModifiers = 'rvmd';
68 #undef B_TRANSLATION_CONTEXT
69 #define B_TRANSLATION_CONTEXT "Modifier keys window"
72 // #pragma mark - ConflictView
75 ConflictView::ConflictView(const char* name)
77 BView(BRect(0, 0, 15, 15), name, B_FOLLOW_NONE, B_WILL_DRAW),
78 fIcon(NULL),
79 fStopIcon(NULL),
80 fWarnIcon(NULL)
82 _FillIcons();
86 ConflictView::~ConflictView()
88 delete fStopIcon;
89 delete fWarnIcon;
93 void
94 ConflictView::Draw(BRect updateRect)
96 // Draw background
97 if (Parent())
98 SetLowColor(Parent()->ViewColor());
99 else
100 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
102 FillRect(updateRect, B_SOLID_LOW);
104 if (fIcon == NULL)
105 return;
107 // Draw icon
108 SetDrawingMode(B_OP_ALPHA);
109 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
110 DrawBitmapAsync(fIcon, BPoint(0, 0));
114 // get the icon
115 BBitmap*
116 ConflictView::Icon()
118 return fIcon;
122 // show or hide the stop icon
123 void
124 ConflictView::SetStopIcon(bool show)
126 fIcon = show ? fStopIcon : NULL;
127 const char* tip = show ? B_TRANSLATE("Error: duplicate keys")
128 : NULL;
129 SetToolTip(tip);
133 // show or hide the warn icon
134 void
135 ConflictView::SetWarnIcon(bool show)
137 fIcon = show ? fWarnIcon : NULL;
138 const char* tip = show
139 ? B_TRANSLATE("Warning: left and right key roles do not match")
140 : NULL;
141 SetToolTip(tip);
145 // #pragma mark - ConflictView private methods
148 // fill out the icons with the stop and warn symbols from app_server
149 void
150 ConflictView::_FillIcons()
152 // return if the icons have already been filled out
153 if (fStopIcon != NULL && fStopIcon->InitCheck() == B_OK
154 && fWarnIcon != NULL && fWarnIcon->InitCheck() == B_OK) {
155 return;
158 BPath path;
159 status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
160 if (status < B_OK) {
161 FTRACE((stderr,
162 "_FillIcons() - find_directory failed: %s\n",
163 strerror(status)));
164 return;
167 path.Append("app_server");
168 BFile file;
169 status = file.SetTo(path.Path(), B_READ_ONLY);
170 if (status < B_OK) {
171 FTRACE((stderr,
172 "_FillIcons() - BFile init failed: %s\n",
173 strerror(status)));
174 return;
177 BResources resources;
178 status = resources.SetTo(&file);
179 if (status < B_OK) {
180 FTRACE((stderr,
181 "_FillIcons() - BResources init failed: %s\n",
182 strerror(status)));
183 return;
186 size_t size = 0;
188 if (fStopIcon == NULL) {
189 // Allocate the fStopIcon bitmap
190 fStopIcon = new (std::nothrow) BBitmap(BRect(0, 0, 15, 15), 0,
191 B_RGBA32);
192 if (fStopIcon->InitCheck() != B_OK) {
193 FTRACE((stderr, "_FillIcons() - No memory for stop bitmap\n"));
194 delete fStopIcon;
195 fStopIcon = NULL;
196 return;
199 // load stop icon bitmap from app_server
200 const uint8* stopVector
201 = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, "stop",
202 &size);
203 if (stopVector == NULL
204 || BIconUtils::GetVectorIcon(stopVector, size, fStopIcon)
205 != B_OK) {
206 delete fStopIcon;
207 fStopIcon = NULL;
211 if (fWarnIcon == NULL) {
212 // Allocate the fWarnIcon bitmap
213 fWarnIcon = new (std::nothrow) BBitmap(BRect(0, 0, 15, 15), 0,
214 B_RGBA32);
215 if (fWarnIcon->InitCheck() != B_OK) {
216 FTRACE((stderr, "_FillIcons() - No memory for warn bitmap\n"));
217 delete fWarnIcon;
218 fWarnIcon = NULL;
219 return;
222 // load warn icon bitmap from app_server
223 const uint8* warnVector
224 = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, "warn",
225 &size);
226 if (warnVector == NULL
227 || BIconUtils::GetVectorIcon(warnVector, size, fWarnIcon)
228 != B_OK) {
229 delete fWarnIcon;
230 fWarnIcon = NULL;
236 // #pragma mark - ModifierKeysWindow
239 ModifierKeysWindow::ModifierKeysWindow()
241 BWindow(BRect(0, 0, 360, 220), B_TRANSLATE("Modifier keys"),
242 B_FLOATING_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE
243 | B_AUTO_UPDATE_SIZE_LIMITS)
245 get_key_map(&fCurrentMap, &fCurrentBuffer);
246 get_key_map(&fSavedMap, &fSavedBuffer);
248 BStringView* keyRole = new BStringView("key role",
249 B_TRANSLATE_COMMENT("Role", "As in the role of a modifier key"));
250 keyRole->SetAlignment(B_ALIGN_RIGHT);
251 keyRole->SetFont(be_bold_font);
253 BStringView* keyLabel = new BStringView("key label",
254 B_TRANSLATE_COMMENT("Key", "As in a computer keyboard key"));
255 keyLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
256 keyLabel->SetFont(be_bold_font);
258 BMenuField* shiftMenuField = _CreateShiftMenuField();
259 shiftMenuField->SetAlignment(B_ALIGN_RIGHT);
261 BMenuField* controlMenuField = _CreateControlMenuField();
262 controlMenuField->SetAlignment(B_ALIGN_RIGHT);
264 BMenuField* optionMenuField = _CreateOptionMenuField();
265 optionMenuField->SetAlignment(B_ALIGN_RIGHT);
267 BMenuField* commandMenuField = _CreateCommandMenuField();
268 commandMenuField->SetAlignment(B_ALIGN_RIGHT);
270 fShiftConflictView = new ConflictView("shift warning view");
271 fShiftConflictView->SetExplicitMaxSize(BSize(15, 15));
273 fControlConflictView = new ConflictView("control warning view");
274 fControlConflictView->SetExplicitMaxSize(BSize(15, 15));
276 fOptionConflictView = new ConflictView("option warning view");
277 fOptionConflictView->SetExplicitMaxSize(BSize(15, 15));
279 fCommandConflictView = new ConflictView("command warning view");
280 fCommandConflictView->SetExplicitMaxSize(BSize(15, 15));
282 fCancelButton = new BButton("cancelButton", B_TRANSLATE("Cancel"),
283 new BMessage(B_QUIT_REQUESTED));
285 fRevertButton = new BButton("revertButton", B_TRANSLATE("Revert"),
286 new BMessage(kMsgRevertModifiers));
287 fRevertButton->SetEnabled(false);
289 fOkButton = new BButton("okButton", B_TRANSLATE("Set modifier keys"),
290 new BMessage(kMsgApplyModifiers));
291 fOkButton->MakeDefault(true);
293 BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING)
294 .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
295 .Add(keyRole, 0, 0)
296 .Add(keyLabel, 1, 0)
298 .Add(shiftMenuField->CreateLabelLayoutItem(), 0, 1)
299 .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 1)
300 .Add(shiftMenuField->CreateMenuBarLayoutItem())
301 .Add(fShiftConflictView)
302 .End()
304 .Add(controlMenuField->CreateLabelLayoutItem(), 0, 2)
305 .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 2)
306 .Add(controlMenuField->CreateMenuBarLayoutItem())
307 .Add(fControlConflictView)
308 .End()
310 .Add(optionMenuField->CreateLabelLayoutItem(), 0, 3)
311 .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 3)
312 .Add(optionMenuField->CreateMenuBarLayoutItem())
313 .Add(fOptionConflictView)
314 .End()
316 .Add(commandMenuField->CreateLabelLayoutItem(), 0, 4)
317 .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1, 4)
318 .Add(commandMenuField->CreateMenuBarLayoutItem())
319 .Add(fCommandConflictView)
320 .End()
321 .End()
322 .AddGlue()
323 .AddGroup(B_HORIZONTAL)
324 .Add(fCancelButton)
325 .AddGlue()
326 .Add(fRevertButton)
327 .Add(fOkButton)
328 .End()
329 .SetInsets(B_USE_WINDOW_SPACING)
330 .End();
332 _MarkMenuItems();
333 _ValidateDuplicateKeys();
335 PostMessage(kMsgHideShowIcons);
339 ModifierKeysWindow::~ModifierKeysWindow()
341 be_app->PostMessage(kMsgCloseModifierKeysWindow);
345 void
346 ModifierKeysWindow::MessageReceived(BMessage* message)
348 switch (message->what) {
349 case kMsgHideShowIcons:
350 _HideShowIcons();
351 break;
353 case kMsgUpdateModifier:
355 int32 menuitem = MENU_ITEM_SHIFT;
356 int32 key = -1;
358 for (; menuitem <= MENU_ITEM_COMMAND; menuitem++) {
359 if (message->FindInt32(_KeyToString(menuitem), &key) == B_OK)
360 break;
363 if (key == -1)
364 return;
366 // menuitem contains the item we want to set
367 // key contains the item we want to set it to.
369 switch (menuitem) {
370 case MENU_ITEM_SHIFT:
371 fCurrentMap->left_shift_key = _KeyToKeyCode(key);
372 fCurrentMap->right_shift_key = _KeyToKeyCode(key, true);
373 break;
375 case MENU_ITEM_CONTROL:
376 fCurrentMap->left_control_key = _KeyToKeyCode(key);
377 fCurrentMap->right_control_key = _KeyToKeyCode(key, true);
378 break;
380 case MENU_ITEM_OPTION:
381 fCurrentMap->left_option_key = _KeyToKeyCode(key);
382 fCurrentMap->right_option_key = _KeyToKeyCode(key, true);
383 break;
385 case MENU_ITEM_COMMAND:
386 fCurrentMap->left_command_key = _KeyToKeyCode(key);
387 fCurrentMap->right_command_key = _KeyToKeyCode(key, true);
388 break;
391 _MarkMenuItems();
392 _ValidateDuplicateKeys();
393 _HideShowIcons();
395 // enable/disable revert button
396 fRevertButton->SetEnabled(
397 memcmp(fCurrentMap, fSavedMap, sizeof(key_map)));
398 break;
401 // OK button
402 case kMsgApplyModifiers:
404 // if duplicate modifiers are found, don't update
405 if (_DuplicateKeys() != 0)
406 break;
408 BMessage* updateModifiers = new BMessage(kMsgUpdateModifierKeys);
410 if (fCurrentMap->left_shift_key != fSavedMap->left_shift_key) {
411 updateModifiers->AddUInt32("left_shift_key",
412 fCurrentMap->left_shift_key);
415 if (fCurrentMap->right_shift_key != fSavedMap->right_shift_key) {
416 updateModifiers->AddUInt32("right_shift_key",
417 fCurrentMap->right_shift_key);
420 if (fCurrentMap->left_control_key != fSavedMap->left_control_key) {
421 updateModifiers->AddUInt32("left_control_key",
422 fCurrentMap->left_control_key);
425 if (fCurrentMap->right_control_key
426 != fSavedMap->right_control_key) {
427 updateModifiers->AddUInt32("right_control_key",
428 fCurrentMap->right_control_key);
431 if (fCurrentMap->left_option_key != fSavedMap->left_option_key) {
432 updateModifiers->AddUInt32("left_option_key",
433 fCurrentMap->left_option_key);
436 if (fCurrentMap->right_option_key != fSavedMap->right_option_key) {
437 updateModifiers->AddUInt32("right_option_key",
438 fCurrentMap->right_option_key);
441 if (fCurrentMap->left_command_key != fSavedMap->left_command_key) {
442 updateModifiers->AddUInt32("left_command_key",
443 fCurrentMap->left_command_key);
446 if (fCurrentMap->right_command_key
447 != fSavedMap->right_command_key) {
448 updateModifiers->AddUInt32("right_command_key",
449 fCurrentMap->right_command_key);
452 // KeymapWindow updates the modifiers
453 be_app->PostMessage(updateModifiers);
455 // we are done here, close the window
456 this->PostMessage(B_QUIT_REQUESTED);
457 break;
460 // Revert button
461 case kMsgRevertModifiers:
462 memcpy(fCurrentMap, fSavedMap, sizeof(key_map));
464 _MarkMenuItems();
465 _ValidateDuplicateKeys();
466 _HideShowIcons();
468 fRevertButton->SetEnabled(false);
469 break;
471 default:
472 BWindow::MessageReceived(message);
477 // #pragma mark - ModifierKeysWindow private methods
480 BMenuField*
481 ModifierKeysWindow::_CreateShiftMenuField()
483 fShiftMenu = new BPopUpMenu(
484 B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_SHIFT)), true, true);
486 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
487 if (key == MENU_ITEM_SEPERATOR) {
488 // add separator item
489 BSeparatorItem* separator = new BSeparatorItem;
490 fShiftMenu->AddItem(separator, MENU_ITEM_SEPERATOR);
491 continue;
494 BMessage* message = new BMessage(kMsgUpdateModifier);
495 message->AddInt32(_KeyToString(MENU_ITEM_SHIFT), key);
496 BMenuItem* item = new BMenuItem(
497 B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message);
499 fShiftMenu->AddItem(item, key);
502 fShiftMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
503 B_ALIGN_VERTICAL_UNSET));
505 return new BMenuField(B_TRANSLATE_COMMENT("Shift:", "Shift key role name"),
506 fShiftMenu);
510 BMenuField*
511 ModifierKeysWindow::_CreateControlMenuField()
513 fControlMenu = new BPopUpMenu(
514 B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_CONTROL)), true, true);
516 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
517 if (key == MENU_ITEM_SEPERATOR) {
518 // add separator item
519 BSeparatorItem* separator = new BSeparatorItem;
520 fControlMenu->AddItem(separator, MENU_ITEM_SEPERATOR);
521 continue;
524 BMessage* message = new BMessage(kMsgUpdateModifier);
525 message->AddInt32(_KeyToString(MENU_ITEM_CONTROL), key);
526 BMenuItem* item = new BMenuItem(
527 B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message);
529 fControlMenu->AddItem(item, key);
532 fControlMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
533 B_ALIGN_VERTICAL_UNSET));
535 return new BMenuField(B_TRANSLATE_COMMENT("Control:",
536 "Control key role name"), fControlMenu);
540 BMenuField*
541 ModifierKeysWindow::_CreateOptionMenuField()
543 fOptionMenu = new BPopUpMenu(
544 B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_OPTION)), true, true);
546 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
547 if (key == MENU_ITEM_SEPERATOR) {
548 // add separator item
549 BSeparatorItem* separator = new BSeparatorItem;
550 fOptionMenu->AddItem(separator, MENU_ITEM_SEPERATOR);
551 continue;
554 BMessage* message = new BMessage(kMsgUpdateModifier);
555 message->AddInt32(_KeyToString(MENU_ITEM_OPTION), key);
556 BMenuItem* item = new BMenuItem(
557 B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message);
559 fOptionMenu->AddItem(item, key);
562 fOptionMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
563 B_ALIGN_VERTICAL_UNSET));
565 return new BMenuField(B_TRANSLATE_COMMENT("Option:",
566 "Option key role name"), fOptionMenu);
570 BMenuField*
571 ModifierKeysWindow::_CreateCommandMenuField()
573 fCommandMenu = new BPopUpMenu(
574 B_TRANSLATE_NOCOLLECT(_KeyToString(MENU_ITEM_COMMAND)), true, true);
576 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
577 if (key == MENU_ITEM_SEPERATOR) {
578 // add separator item
579 BSeparatorItem* separator = new BSeparatorItem;
580 fCommandMenu->AddItem(separator, MENU_ITEM_SEPERATOR);
581 continue;
584 BMessage* message = new BMessage(kMsgUpdateModifier);
585 message->AddInt32(_KeyToString(MENU_ITEM_COMMAND), key);
586 BMenuItem* item = new BMenuItem(
587 B_TRANSLATE_NOCOLLECT(_KeyToString(key)), message);
588 fCommandMenu->AddItem(item, key);
591 fCommandMenu->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
592 B_ALIGN_VERTICAL_UNSET));
594 return new BMenuField(B_TRANSLATE_COMMENT("Command:",
595 "Command key role name"), fCommandMenu);
599 void
600 ModifierKeysWindow::_MarkMenuItems()
602 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_DISABLED; key++) {
603 if (key == MENU_ITEM_SEPERATOR)
604 continue;
606 if (fCurrentMap->left_shift_key == _KeyToKeyCode(key)
607 && fCurrentMap->right_shift_key == _KeyToKeyCode(key, true)) {
608 fShiftMenu->ItemAt(key)->SetMarked(true);
611 if (fCurrentMap->left_control_key == _KeyToKeyCode(key)
612 && fCurrentMap->right_control_key == _KeyToKeyCode(key, true)) {
613 fControlMenu->ItemAt(key)->SetMarked(true);
616 if (fCurrentMap->left_option_key == _KeyToKeyCode(key)
617 && fCurrentMap->right_option_key == _KeyToKeyCode(key, true)) {
618 fOptionMenu->ItemAt(key)->SetMarked(true);
621 if (fCurrentMap->left_command_key == _KeyToKeyCode(key)
622 && fCurrentMap->right_command_key == _KeyToKeyCode(key, true)) {
623 fCommandMenu->ItemAt(key)->SetMarked(true);
627 // Set the warning icon if not marked
628 BBitmap* shiftIcon = fShiftConflictView->Icon();
629 BBitmap* controlIcon = fControlConflictView->Icon();
630 BBitmap* optionIcon = fOptionConflictView->Icon();
631 BBitmap* commandIcon = fCommandConflictView->Icon();
633 fShiftConflictView->SetWarnIcon(fShiftMenu->FindMarked() == NULL);
634 fControlConflictView->SetWarnIcon(fControlMenu->FindMarked() == NULL);
635 fOptionConflictView->SetWarnIcon(fOptionMenu->FindMarked() == NULL);
636 fCommandConflictView->SetWarnIcon(fCommandMenu->FindMarked() == NULL);
638 // if there was a change invalidate the view
639 if (shiftIcon != fShiftConflictView->Icon())
640 fShiftConflictView->Invalidate();
642 if (controlIcon != fControlConflictView->Icon())
643 fControlConflictView->Invalidate();
645 if (optionIcon != fOptionConflictView->Icon())
646 fOptionConflictView->Invalidate();
648 if (commandIcon != fCommandConflictView->Icon())
649 fCommandConflictView->Invalidate();
653 // get the string for a modifier key
654 const char*
655 ModifierKeysWindow::_KeyToString(int32 key)
657 switch (key) {
658 case MENU_ITEM_SHIFT:
659 return B_TRANSLATE_COMMENT("Shift key",
660 "Label of key above Ctrl, usually Shift");
662 case MENU_ITEM_CONTROL:
663 return B_TRANSLATE_COMMENT("Ctrl key",
664 "Label of key farthest from the spacebar, usually Ctrl"
665 "e.g. Strg for German keyboard");
667 case MENU_ITEM_OPTION:
668 return B_TRANSLATE_COMMENT("Win/Cmd key",
669 "Label of the \"Windows\" key (PC)/Command key (Mac)");
671 case MENU_ITEM_COMMAND:
672 return B_TRANSLATE_COMMENT("Alt/Opt key",
673 "Label of Alt key (PC)/Option key (Mac)");
675 case MENU_ITEM_DISABLED:
676 return B_TRANSLATE_COMMENT("Disabled", "Do nothing");
679 return "";
683 // get the keycode for a modifier key
684 uint32
685 ModifierKeysWindow::_KeyToKeyCode(int32 key, bool right)
687 switch (key) {
688 case MENU_ITEM_SHIFT:
689 if (right)
690 return 0x56;
691 return 0x4b;
693 case MENU_ITEM_CONTROL:
694 if (right)
695 return 0x60;
696 return 0x5c;
698 case MENU_ITEM_OPTION:
699 if (right)
700 return 0x67;
701 return 0x66;
703 case MENU_ITEM_COMMAND:
704 if (right)
705 return 0x5f;
706 return 0x5d;
708 case MENU_ITEM_DISABLED:
709 return 0;
712 return 0;
716 // validate duplicate keys
717 void
718 ModifierKeysWindow::_ValidateDuplicateKeys()
720 uint32 dupMask = _DuplicateKeys();
722 BBitmap* shiftIcon = fShiftConflictView->Icon();
723 BBitmap* controlIcon = fControlConflictView->Icon();
724 BBitmap* optionIcon = fOptionConflictView->Icon();
725 BBitmap* commandIcon = fCommandConflictView->Icon();
727 if ((dupMask & SHIFT_KEY) != 0)
728 fShiftConflictView->SetStopIcon(true);
730 if ((dupMask & CONTROL_KEY) != 0)
731 fControlConflictView->SetStopIcon(true);
733 if ((dupMask & OPTION_KEY) != 0)
734 fOptionConflictView->SetStopIcon(true);
736 if ((dupMask & COMMAND_KEY) != 0)
737 fCommandConflictView->SetStopIcon(true);
739 fOkButton->SetEnabled(dupMask == 0);
741 // if there was a change invalidate the view
742 if (shiftIcon != fShiftConflictView->Icon())
743 fShiftConflictView->Invalidate();
745 if (controlIcon != fControlConflictView->Icon())
746 fControlConflictView->Invalidate();
748 if (optionIcon != fOptionConflictView->Icon())
749 fOptionConflictView->Invalidate();
751 if (commandIcon != fCommandConflictView->Icon())
752 fCommandConflictView->Invalidate();
756 // return a mask marking which keys are duplicates of each other for
757 // validation. Shift = 0, Control = 1, Option = 2, Command = 3
758 uint32
759 ModifierKeysWindow::_DuplicateKeys()
761 uint32 duplicateMask = 0;
763 for (int32 testKey = MENU_ITEM_SHIFT; testKey <= MENU_ITEM_COMMAND;
764 testKey++) {
765 uint32 testLeft = 0;
766 uint32 testRight = 0;
768 switch (testKey) {
769 case MENU_ITEM_SHIFT:
770 testLeft = fCurrentMap->left_shift_key;
771 testRight = fCurrentMap->right_shift_key;
772 break;
774 case MENU_ITEM_CONTROL:
775 testLeft = fCurrentMap->left_control_key;
776 testRight = fCurrentMap->right_control_key;
777 break;
779 case MENU_ITEM_OPTION:
780 testLeft = fCurrentMap->left_option_key;
781 testRight = fCurrentMap->right_option_key;
782 break;
784 case MENU_ITEM_COMMAND:
785 testLeft = fCurrentMap->left_command_key;
786 testRight = fCurrentMap->right_command_key;
787 break;
790 if (testLeft == 0 && testRight == 0)
791 continue;
793 for (int32 key = MENU_ITEM_SHIFT; key <= MENU_ITEM_COMMAND; key++) {
794 if (key == testKey) {
795 // skip over yourself
796 continue;
799 uint32 left = 0;
800 uint32 right = 0;
802 switch (key) {
803 case MENU_ITEM_SHIFT:
804 left = fCurrentMap->left_shift_key;
805 right = fCurrentMap->right_shift_key;
806 break;
808 case MENU_ITEM_CONTROL:
809 left = fCurrentMap->left_control_key;
810 right = fCurrentMap->right_control_key;
811 break;
813 case MENU_ITEM_OPTION:
814 left = fCurrentMap->left_option_key;
815 right = fCurrentMap->right_option_key;
816 break;
818 case MENU_ITEM_COMMAND:
819 left = fCurrentMap->left_command_key;
820 right = fCurrentMap->right_command_key;
821 break;
824 if (left == 0 && right == 0)
825 continue;
827 if (left == testLeft || right == testRight) {
828 duplicateMask |= 1 << testKey;
829 duplicateMask |= 1 << key;
834 return duplicateMask;
838 void
839 ModifierKeysWindow::_HideShowIcons()
841 if (fShiftConflictView->Icon() == NULL) {
842 while (!fShiftConflictView->IsHidden())
843 fShiftConflictView->Hide();
844 } else {
845 while (fShiftConflictView->IsHidden())
846 fShiftConflictView->Show();
849 if (fControlConflictView->Icon() == NULL) {
850 while (!fControlConflictView->IsHidden())
851 fControlConflictView->Hide();
852 } else {
853 while (fControlConflictView->IsHidden())
854 fControlConflictView->Show();
857 if (fOptionConflictView->Icon() == NULL) {
858 while (!fOptionConflictView->IsHidden())
859 fOptionConflictView->Hide();
860 } else {
861 while (fOptionConflictView->IsHidden())
862 fOptionConflictView->Show();
865 if (fCommandConflictView->Icon() == NULL) {
866 while (!fCommandConflictView->IsHidden())
867 fCommandConflictView->Hide();
868 } else {
869 while (fCommandConflictView->IsHidden())
870 fCommandConflictView->Show();