diff --git a/headers/os/interface/Window.h b/headers/os/interface/Window.h index 15064265bb..1d966fcdcf 100644 --- a/headers/os/interface/Window.h +++ b/headers/os/interface/Window.h @@ -259,6 +259,7 @@ public: // Private or reserved --------------------------------------------------------- private: typedef BLooper inherited; + class Shortcut; friend class BApplication; friend class BBitmap; @@ -287,7 +288,7 @@ private: BWindow &operator=(BWindow&); BWindow(BRect frame, int32 bitmapToken); - void InitData(BRect frame, const char* title, + void _InitData(BRect frame, const char* title, window_look look, window_feel feel, uint32 flags, uint32 workspace, int32 bitmapToken = -1); @@ -307,9 +308,9 @@ private: drawing_mode dragMode, BHandler* reply_to); */ - void prepareView(BView* aView); // changed from view_builder(BView* a_view); - void attachView(BView* aView); // changed from attach_builder(BView* a_view); - void detachView(BView* aView); // changed from detach_builder(BView* a_view); + void prepareView(BView* aView); + void attachView(BView* aView); + void detachView(BView* aView); //int32 get_server_token() const; BMessage *extract_drop(BMessage* an_event, BHandler* *target); //void movesize(uint32 opcode, float h, float v); @@ -334,16 +335,16 @@ private: //void post_message(BMessage* message); //void SetLocalTitle(const char* new_title); //void enable_pulsing(bool enable); - BHandler *determine_target(BMessage* msg, BHandler* target, bool pref); + BHandler *_DetermineTarget(BMessage* message, BHandler* target); //void kb_navigate(); //void navigate_to_next(int32 direction, bool group = false); //void set_focus(BView* focus, bool notify_input_server); // what does notify_input_server mean??? why??? bool InUpdate(); void DequeueAll(); //bool find_token_and_handler(BMessage* msg, int32* token, BHandler* *handler); - window_type composeType(window_look look, // changed from: compose_type(...) + window_type _ComposeType(window_look look, window_feel feel) const; - void decomposeType(window_type type, // changed from: decompose_type(...) + void _DecomposeType(window_type type, window_look* look, window_feel* feel) const; @@ -353,7 +354,7 @@ private: void BuildTopView(); void setFocus(BView *focusView, bool notifyIputServer = false); - int32 findShortcut(uint32 key, uint32 modifiers); + Shortcut* _FindShortcut(uint32 key, uint32 modifiers); bool findHandler(BView* start, BHandler* handler); BView* findView(BView* aView, const char* viewName) const; BView* findView(BView* aView, BPoint point) const; @@ -386,13 +387,13 @@ private: uint32 fFlags; uint32 _unused0[2]; - BView *top_view; + BView *fTopView; BView *fFocus; BView *fLastMouseMovedView; uint32 _unused1; BMenuBar *fKeyMenuBar; BButton *fDefaultButton; - BList accelList; + BList fShortcuts; int32 fTopViewToken; bool fPulseEnabled; bool fViewsNeedPulse; // not yet used diff --git a/headers/private/interface/WindowAux.h b/headers/private/interface/WindowAux.h deleted file mode 100644 index 8174a2ec9b..0000000000 --- a/headers/private/interface/WindowAux.h +++ /dev/null @@ -1,69 +0,0 @@ -//------------------------------------------------------------------------------ -// Copyright (c) 2001-2002, OpenBeOS -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// -// File Name: WindowAux.h -// Author: Adrian Oanca (oancaadrian@yahoo.com) -// Description: BWindowAux.h contains helper definitions for BWindow class -// -//------------------------------------------------------------------------------ - -#ifndef _WINDOWAUX_H -#define _WINDOWAUX_H - -// Standard Includes ----------------------------------------------------------- - -// System Includes ------------------------------------------------------------- -#include -#include -#include - -// Project Includes ------------------------------------------------------------ - -// Local Includes -------------------------------------------------------------- - -// Local Defines --------------------------------------------------------------- - -// Globals --------------------------------------------------------------------- - - -struct _BCmdKey{ - uint32 key; - uint32 modifiers; - BMessage* message; - BHandler* target; - int32 targetToken; - - _BCmdKey(uint32 k, uint32 mod, BMessage* m = NULL) - : key(k), - modifiers(mod), - message(m), - target(NULL), - targetToken(B_ANY_TOKEN) - { - } - ~_BCmdKey() - { - delete message; - } - -}; - -#endif // _WINDOWAUX_H diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index 8069978a7d..e65934ad89 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -48,6 +47,32 @@ # define STRACE(x) ; #endif + +class BWindow::Shortcut { + public: + Shortcut(uint32 key, uint32 modifiers, BMenuItem* item); + Shortcut(uint32 key, uint32 modifiers, BMessage* message, BHandler* target); + ~Shortcut(); + + bool Matches(uint32 key, uint32 modifiers) const; + + BMenuItem* MenuItem() const { return fMenuItem; } + BMessage* Message() const { return fMessage; } + BHandler* Target() const { return fTarget; } + + static uint32 AllowedModifiers(); + static uint32 PrepareKey(uint32 key); + static uint32 PrepareModifiers(uint32 modifiers); + + private: + uint32 fKey; + uint32 fModifiers; + BMenuItem* fMenuItem; + BMessage* fMessage; + BHandler* fTarget; +}; + + using BPrivate::gDefaultTokens; static property_info sWindowPropInfo[] = { @@ -115,19 +140,81 @@ _set_menu_sem_(BWindow *window, sem_id sem) // #pragma mark - +BWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMenuItem* item) + : + fKey(PrepareKey(key)), + fModifiers(PrepareModifiers(modifiers)), + fMenuItem(item), + fMessage(NULL), + fTarget(NULL) +{ +} + + +BWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMessage* message, + BHandler* target) + : + fKey(PrepareKey(key)), + fModifiers(PrepareModifiers(modifiers)), + fMenuItem(NULL), + fMessage(message), + fTarget(target) +{ +} + + +BWindow::Shortcut::~Shortcut() +{ + // we own the message, if any + delete fMessage; +} + + +bool +BWindow::Shortcut::Matches(uint32 key, uint32 modifiers) const +{ + return fKey == key && fModifiers == modifiers; +} + + +/*static*/ +uint32 +BWindow::Shortcut::AllowedModifiers() +{ + return B_COMMAND_KEY | B_OPTION_KEY | B_SHIFT_KEY + | B_CONTROL_KEY | B_MENU_KEY; +} + + +/*static*/ +uint32 +BWindow::Shortcut::PrepareModifiers(uint32 modifiers) +{ + return (modifiers & AllowedModifiers()) | B_COMMAND_KEY; +} + + +/*static*/ +uint32 +BWindow::Shortcut::PrepareKey(uint32 key) +{ + return tolower(key); + // TODO: support unicode and/or more intelligent key mapping +} + + +// #pragma mark - + + BWindow::BWindow(BRect frame, const char* title, window_type type, uint32 flags, uint32 workspace) : BLooper(title) { - #ifdef DEBUG_WIN - printf("BWindow::BWindow()\n"); - #endif window_look look; window_feel feel; + _DecomposeType(type, &look, &feel); - decomposeType(type, &look, &feel); - - InitData(frame, title, look, feel, flags, workspace); + _InitData(frame, title, look, feel, flags, workspace); } @@ -135,7 +222,7 @@ BWindow::BWindow(BRect frame, const char* title, window_look look, window_feel f uint32 flags, uint32 workspace) : BLooper(title) { - InitData(frame, title, look, feel, flags, workspace); + _InitData(frame, title, look, feel, flags, workspace); } @@ -161,10 +248,10 @@ BWindow::BWindow(BMessage* data) uint32 type; if (data->FindInt32("_type", (int32*)&type) == B_OK) - decomposeType((window_type)type, &fLook, &fFeel); + _DecomposeType((window_type)type, &fLook, &fFeel); // connect to app_server and initialize data - InitData(fFrame, title, look, feel, fFlags, workspaces); + _InitData(fFrame, title, look, feel, fFlags, workspaces); if (data->FindFloat("_zoom", 0, &fMaxZoomWidth) == B_OK && data->FindFloat("_zoom", 1, &fMaxZoomHeight) == B_OK) @@ -195,21 +282,21 @@ BWindow::BWindow(BRect frame, int32 bitmapToken) : BLooper("offscreen bitmap") { // TODO: Implement for real - decomposeType(B_UNTYPED_WINDOW, &fLook, &fFeel); - InitData(frame, "offscreen", fLook, fFeel, 0, 0, bitmapToken); + _DecomposeType(B_UNTYPED_WINDOW, &fLook, &fFeel); + _InitData(frame, "offscreen", fLook, fFeel, 0, 0, bitmapToken); } BWindow::~BWindow() { - // the following lines, remove all existing shortcuts and delete accelList - int32 noOfItems = accelList.CountItems(); - for (int index = noOfItems-1; index >= 0; index--) { - delete (_BCmdKey*)accelList.ItemAt(index); + // remove all existing shortcuts + int32 noOfItems = fShortcuts.CountItems(); + for (int32 index = noOfItems - 1; index >= 0; index--) { + delete (Shortcut *)fShortcuts.ItemAt(index); } // TODO: release other dynamically-allocated objects - + // Deleting this semaphore will tell open menus to quit. if (fMenuSem > 0) delete_sem(fMenuSem); @@ -252,7 +339,7 @@ BWindow::Archive(BMessage* data, bool deep) const data->AddInt32("_flags", fFlags); data->AddInt32("_wspace", (uint32)Workspaces()); - if (!composeType(fLook, fFeel)) + if (!_ComposeType(fLook, fFeel)) data->AddInt32("_type", (uint32)Type()); if (fMaxZoomWidth != 32768.0 || fMaxZoomHeight != 32768.0) { @@ -319,28 +406,28 @@ BWindow::Quit() void BWindow::AddChild(BView *child, BView *before) { - top_view->AddChild(child, before); + fTopView->AddChild(child, before); } bool BWindow::RemoveChild(BView *child) { - return top_view->RemoveChild(child); + return fTopView->RemoveChild(child); } int32 BWindow::CountChildren() const { - return top_view->CountChildren(); + return fTopView->CountChildren(); } BView * BWindow::ChildAt(int32 index) const { - return top_view->ChildAt(index); + return fTopView->ChildAt(index); } @@ -715,12 +802,12 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target) case B_UNMAPPED_KEY_DOWN: case B_UNMAPPED_KEY_UP: case B_MODIFIERS_CHANGED: - if (target != this && target != top_view) + if (target != this && target != fTopView) target->MessageReceived(msg); break; case B_MOUSE_WHEEL_CHANGED: - if (target != this && target != top_view) + if (target != this && target != fTopView) target->MessageReceived(msg); break; @@ -735,7 +822,7 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target) msg->FindInt32("buttons", (int32 *)&buttons); msg->FindInt32("clicks", &clicks); - if (target && target != this && target != top_view) { + if (target && target != this && target != fTopView) { if (BView *view = dynamic_cast(target)) { view->ConvertFromScreen(&where); view->MouseDown(where); @@ -752,7 +839,7 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target) msg->FindPoint("where", &where); msg->FindInt32("modifiers", (int32 *)&modifiers); - if (target && target != this && target != top_view) { + if (target && target != this && target != fTopView) { if (BView *view = dynamic_cast(target)) { view->ConvertFromScreen(&where); view->MouseUp(where); @@ -770,7 +857,7 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target) msg->FindPoint("where", &where); msg->FindInt32("buttons", (int32 *)&buttons); msg->FindInt32("transit", (int32 *)&transit); - if (target && target != this && target != top_view) { + if (target && target != this && target != fTopView) { if (BView *view = dynamic_cast(target)) { if (fLastMouseMovedView != view) { if (fLastMouseMovedView) { @@ -790,7 +877,7 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target) case B_PULSE: if (fPulseEnabled) { - top_view->_Pulse(); + fTopView->_Pulse(); fLink->Flush(); } break; @@ -809,7 +896,7 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target) msg->FindInt32("_token", &token); fLink->StartMessage(AS_BEGIN_UPDATE); - DoUpdate(top_view, updateRect); + DoUpdate(fTopView, updateRect); fLink->StartMessage(AS_END_UPDATE); fLink->Flush(); break; @@ -834,7 +921,7 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target) msg->FindPoint("where", i, &frameLeftTop); msg->FindFloat("width", i, &width); msg->FindFloat("height", i, &height); - if ((view = findView(top_view, token))) { + if ((view = findView(fTopView, token))) { // update the views offset in parent if (view->LeftTop() != frameLeftTop) { //printf("updating position (%.1f, %.1f): %s\n", frameLeftTop.x, frameLeftTop.y, view->Name()); @@ -1112,54 +1199,44 @@ BWindow::PulseRate() const void BWindow::AddShortcut(uint32 key, uint32 modifiers, BMenuItem *item) { - if (item->Message()) - AddShortcut(key, modifiers, new BMessage(*item->Message()), this); -} + Shortcut* shortcut = new Shortcut(key, modifiers, item); - -void -BWindow::AddShortcut(uint32 key, uint32 modifiers, BMessage *msg) -{ - AddShortcut(key, modifiers, msg, this); -} - - -void -BWindow::AddShortcut(uint32 key, uint32 modifiers, BMessage *msg, BHandler *target) -{ - // NOTE: I'm not sure if it is OK to use 'key' - - if (msg == NULL) - return; - - int64 when = real_time_clock_usecs(); - msg->AddInt64("when", when); - - // TODO: support unicode here - key = tolower(key); - modifiers = modifiers | B_COMMAND_KEY; - - _BCmdKey *cmdKey = new _BCmdKey(key, modifiers, msg); - - if (target) - cmdKey->targetToken = _get_object_token_(target); - - // removes the shortcut from accelList if it exists! + // removes the shortcut if it already exists! RemoveShortcut(key, modifiers); - accelList.AddItem((void*)cmdKey); + fShortcuts.AddItem(shortcut); +} + + +void +BWindow::AddShortcut(uint32 key, uint32 modifiers, BMessage *message) +{ + AddShortcut(key, modifiers, message, this); +} + + +void +BWindow::AddShortcut(uint32 key, uint32 modifiers, BMessage *message, BHandler *target) +{ + if (message == NULL) + return; + + Shortcut* shortcut = new Shortcut(key, modifiers, message, target); + + // removes the shortcut if it already exists! + RemoveShortcut(key, modifiers); + + fShortcuts.AddItem(shortcut); } void BWindow::RemoveShortcut(uint32 key, uint32 modifiers) { - int32 index = findShortcut(key, modifiers | B_COMMAND_KEY); - if (index >=0) { - _BCmdKey *cmdKey = (_BCmdKey *)accelList.ItemAt(index); - - accelList.RemoveItem(index); - delete cmdKey; + Shortcut* shortcut = _FindShortcut(key, modifiers); + if (shortcut != NULL) { + fShortcuts.RemoveItem(shortcut); + delete shortcut; } } @@ -1252,7 +1329,7 @@ BView * BWindow::FindView(const char *viewName) const { // TODO: What about locking?!? - return findView(top_view, viewName); + return findView(fTopView, viewName); } @@ -1260,13 +1337,12 @@ BView * BWindow::FindView(BPoint point) const { // TODO: What about locking?!? - return findView(top_view, point); + return findView(fTopView, point); } BView *BWindow::CurrentFocus() const { - // TODO: What about locking?!? return fFocus; } @@ -1521,7 +1597,7 @@ BWindow::SetType(window_type type) { window_look look; window_feel feel; - decomposeType(type, &look, &feel); + _DecomposeType(type, &look, &feel); status_t status = SetLook(look); if (status == B_OK) @@ -1534,7 +1610,7 @@ BWindow::SetType(window_type type) window_type BWindow::Type() const { - return composeType(fLook, fFeel); + return _ComposeType(fLook, fFeel); } @@ -1906,7 +1982,7 @@ BWindow::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier, if (propertyInfo.FindMatch(msg, index, specifier, what, property) >= 0) { if (!strcmp(property, "View")) { // we will NOT pop the current specifier - return top_view; + return fTopView; } else if (!strcmp(property, "MenuBar")) { if (fKeyMenuBar) { msg->PopSpecifier(); @@ -1930,7 +2006,7 @@ BWindow::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier, void -BWindow::InitData(BRect frame, const char* title, window_look look, +BWindow::_InitData(BRect frame, const char* title, window_look look, window_feel feel, uint32 flags, uint32 workspace, int32 bitmapToken) { STRACE(("BWindow::InitData()\n")); @@ -1955,18 +2031,21 @@ BWindow::InitData(BRect frame, const char* title, window_look look, fActive = false; fShowLevel = 1; - top_view = NULL; + fTopView = NULL; fFocus = NULL; fLastMouseMovedView = NULL; fKeyMenuBar = NULL; fDefaultButton = NULL; + // Shortcut 'Q' is handled in _HandleKeyDown() directly, as its message + // get sent to the application, and not one of our handlers + if ((fFlags & B_NOT_CLOSABLE) == 0) + AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); + AddShortcut('X', B_COMMAND_KEY, new BMessage(B_CUT), NULL); AddShortcut('C', B_COMMAND_KEY, new BMessage(B_COPY), NULL); AddShortcut('V', B_COMMAND_KEY, new BMessage(B_PASTE), NULL); AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), NULL); - if ((fFlags & B_NOT_CLOSABLE) == 0) - AddShortcut('W', B_COMMAND_KEY, new BMessage(B_CLOSE_REQUESTED)); fPulseEnabled = false; fPulseRate = 0; @@ -2066,7 +2145,7 @@ BWindow::InitData(BRect frame, const char* title, window_look look, STRACE(("Server says that our send port is %ld\n", sendPort)); STRACE(("Window locked?: %s\n", IsLocked() ? "True" : "False")); - // build and register top_view with app_server + // build and register fTopView with app_server BuildTopView(); } @@ -2089,7 +2168,7 @@ BWindow::DequeueAll() // TODO: This here is a nearly full code duplication to BLooper::task_loop -// but with one little difference: It uses the determine_target function +// but with one little difference: It uses the _DetermineTarget() method // to tell what the later target of a message will be, if no explicit target // is supplied. This is important because we need to call the right targets // MessageFilter. For B_KEY_DOWN messages for example, not the BWindow but the @@ -2152,26 +2231,20 @@ BWindow::task_looper() // Use BMessage friend functions to determine if we are using the // preferred handler, or if a target has been specified BHandler* handler; - if (_use_preferred_target_(fLastMessage)) { - handler = fPreferred; + bool usePreferred = _use_preferred_target_(fLastMessage); + if (usePreferred) { + handler = PreferredHandler(); } else { - /** - @note Here is where all the token stuff starts to - make sense. How, exactly, do we determine - what the target BHandler is? If we look at - BMessage, we see an int32 field, fTarget. - Amazingly, we happen to have a global mapping - of BHandler pointers to int32s! - */ gDefaultTokens.GetToken(_get_message_target_(fLastMessage), B_HANDLER_TOKEN, (void **)&handler); } - if (!handler) { - handler = determine_target(fLastMessage, handler, false); - if (!handler) - handler = this; - } + // if a target was given, and we should not use the preferred + // handler, we can just use that one + if (handler == NULL || usePreferred) + handler = _DetermineTarget(fLastMessage, handler); + if (handler == NULL) + handler = this; // Is this a scripting message? (BMessage::HasSpecifiers()) if (fLastMessage->HasSpecifiers()) { @@ -2182,7 +2255,7 @@ BWindow::task_looper() } if (handler) { - // Do filtering + // Do filtering and dispatch message handler = top_level_filter(fLastMessage, handler); if (handler && handler->Looper() == this) DispatchMessage(fLastMessage, handler); @@ -2206,8 +2279,7 @@ BWindow::task_looper() window_type -BWindow::composeType(window_look look, - window_feel feel) const +BWindow::_ComposeType(window_look look, window_feel feel) const { switch (feel) { case B_NORMAL_WINDOW_FEEL: @@ -2245,52 +2317,36 @@ BWindow::composeType(window_look look, void -BWindow::decomposeType(window_type type, window_look *look, - window_feel *feel) const +BWindow::_DecomposeType(window_type type, window_look *_look, + window_feel *_feel) const { switch (type) { - case B_TITLED_WINDOW: - { - *look = B_TITLED_WINDOW_LOOK; - *feel = B_NORMAL_WINDOW_FEEL; - break; - } case B_DOCUMENT_WINDOW: - { - *look = B_DOCUMENT_WINDOW_LOOK; - *feel = B_NORMAL_WINDOW_FEEL; + *_look = B_DOCUMENT_WINDOW_LOOK; + *_feel = B_NORMAL_WINDOW_FEEL; break; - } + case B_MODAL_WINDOW: - { - *look = B_MODAL_WINDOW_LOOK; - *feel = B_MODAL_APP_WINDOW_FEEL; + *_look = B_MODAL_WINDOW_LOOK; + *_feel = B_MODAL_APP_WINDOW_FEEL; break; - } + case B_FLOATING_WINDOW: - { - *look = B_FLOATING_WINDOW_LOOK; - *feel = B_FLOATING_APP_WINDOW_FEEL; + *_look = B_FLOATING_WINDOW_LOOK; + *_feel = B_FLOATING_APP_WINDOW_FEEL; break; - } + case B_BORDERED_WINDOW: - { - *look = B_BORDERED_WINDOW_LOOK; - *feel = B_NORMAL_WINDOW_FEEL; + *_look = B_BORDERED_WINDOW_LOOK; + *_feel = B_NORMAL_WINDOW_FEEL; break; - } + + case B_TITLED_WINDOW: case B_UNTYPED_WINDOW: - { - *look = B_TITLED_WINDOW_LOOK; - *feel = B_NORMAL_WINDOW_FEEL; - break; - } default: - { - *look = B_TITLED_WINDOW_LOOK; - *feel = B_NORMAL_WINDOW_FEEL; + *_look = B_TITLED_WINDOW_LOOK; + *_feel = B_NORMAL_WINDOW_FEEL; break; - } } } @@ -2301,23 +2357,23 @@ BWindow::BuildTopView() STRACE(("BuildTopView(): enter\n")); BRect frame = fFrame.OffsetToCopy(B_ORIGIN); - top_view = new BView(frame, "top_view", + fTopView = new BView(frame, "fTopView", B_FOLLOW_ALL, B_WILL_DRAW); - top_view->top_level_view = true; + fTopView->top_level_view = true; //inhibit check_lock() - fLastViewToken = _get_object_token_(top_view); + fLastViewToken = _get_object_token_(fTopView); - // set top_view's owner, add it to window's eligible handler list + // set fTopView's owner, add it to window's eligible handler list // and also set its next handler to be this window. - STRACE(("Calling setowner top_view = %p this = %p.\n", - top_view, this)); + STRACE(("Calling setowner fTopView = %p this = %p.\n", + fTopView, this)); - top_view->_SetOwner(this); + fTopView->_SetOwner(this); - //we can't use AddChild() because this is the top_view - top_view->attachView(top_view); + //we can't use AddChild() because this is the fTopView + fTopView->attachView(fTopView); STRACE(("BuildTopView ended\n")); } @@ -2370,49 +2426,52 @@ BWindow::handleActivation(bool active) // recursively call hook function 'WindowActivated(bool)' // for all views attached to this window. - top_view->_Activate(active); + fTopView->_Activate(active); } +/*! + \brief Determines the target of a message received. +*/ BHandler * -BWindow::determine_target(BMessage *msg, BHandler *target, bool pref) +BWindow::_DetermineTarget(BMessage *message, BHandler *target) { // TODO: this is mostly guessed; check for correctness. - // I think this function is used to determine if a BView will be - // the target of a message. This is used in the BLooper::task_loop - // to determine what BHandler will dispatch the message and what filters - // should be checked before doing so. - - switch (msg->what) { + + switch (message->what) { case B_KEY_DOWN: case B_KEY_UP: case B_UNMAPPED_KEY_DOWN: case B_UNMAPPED_KEY_UP: case B_MODIFIERS_CHANGED: - case B_MOUSE_WHEEL_CHANGED: // these messages will be dispatched by the focus view later - return fFocus; - + return CurrentFocus(); + case B_MOUSE_DOWN: case B_MOUSE_UP: case B_MOUSE_MOVED: - // TODO: find out how to determine the target for these + case B_MOUSE_WHEEL_CHANGED: + // TODO: the app_server should tell us which view is the target break; - + case B_PULSE: case B_QUIT_REQUESTED: // TODO: test wether R5 will let BView dispatch these messages - break; + return this; case B_VIEW_RESIZED: - case B_VIEW_MOVED: { - int32 token = B_NULL_TOKEN; - msg->FindInt32("_token", &token); - BView *view = findView(top_view, token); + case B_VIEW_MOVED: + { + int32 token; + if (message->FindInt32("_token", &token) != B_OK) + token = B_NULL_TOKEN; + + BView *view = findView(fTopView, token); if (view) return view; break; } + default: break; } @@ -2446,57 +2505,44 @@ BWindow::_HandleKeyDown(char key, uint32 modifiers) // Handle shortcuts if ((modifiers & B_COMMAND_KEY) != 0) { // Command+q has been pressed, so, we will quit + // the shortcut mechanism doesn't allow handlers outside the window if (key == 'Q' || key == 'q') { be_app->PostMessage(B_QUIT_REQUESTED); return true; } - // we only must consider temporary modifiers for the shortcuts - modifiers &= B_COMMAND_KEY | B_OPTION_KEY | B_SHIFT_KEY - | B_CONTROL_KEY | B_MENU_KEY; - - int32 index; - if ((index = findShortcut(key, modifiers)) >= 0) { - _BCmdKey *cmdKey = (_BCmdKey*)accelList.ItemAt(index); - - // TODO: using MessageReceived() here removes the possibility to filter the messages! - - // we'll give the message to the focus view - if (cmdKey->targetToken == B_ANY_TOKEN) { - fFocus->MessageReceived(cmdKey->message); - return true; + Shortcut* shortcut = _FindShortcut(key, modifiers); + if (shortcut != NULL) { + // TODO: would be nice to move this functionality to + // a Shortcut::Invoke() method - but since BMenu::InvokeItem() + // (and BMenuItem::Invoke()) are private, I didn't want + // to mess with them (BMenuItem::Invoke() is public in + // Dano/Zeta, though, maybe we should just follow their + // example) + if (shortcut->MenuItem() != NULL) { + BMenu* menu = shortcut->MenuItem()->Menu(); + if (menu != NULL) + menu->InvokeItem(shortcut->MenuItem(), true); } else { - BHandler *target = NULL; - int32 count = CountHandlers(); + BHandler* target = shortcut->Target(); + if (target == NULL) + target = CurrentFocus(); - // ToDo: this looks wrong: why not just send a message to the - // target? Only if the target is a handler of this looper we - // can do what is done below. + BMessage* message = shortcut->Message(); + if (message->ReplaceInt64("when", system_time()) != B_OK) + message->AddInt64("when", system_time()); - // search for a match through BLooper's list of eligible handlers - for (int32 i = 0; i < count; i++) { - BHandler *handler = HandlerAt(i); - - // do we have a match? - if (_get_object_token_(handler) == cmdKey->targetToken) { - // yes, we do. - target = handler; - break; - } - } - - if (target) - target->MessageReceived(cmdKey->message); - else { - // if no handler was found, BWindow will handle the message - PostMessage(cmdKey->message); - } + PostMessage(message, target); } + return true; } } + // TODO: convert keys to the encoding of the target view + // if is pressed and we have a default button + // TODO: what happens if we have a focus view? This code looks wrong if (DefaultButton() && key == B_ENTER) { const char *chars; CurrentMessage()->FindString("bytes", &chars); @@ -2543,21 +2589,22 @@ BWindow::ConvertToMessage(void *raw, int32 code) } -int32 -BWindow::findShortcut(uint32 key, uint32 modifiers) +BWindow::Shortcut * +BWindow::_FindShortcut(uint32 key, uint32 modifiers) { - int32 count = accelList.CountItems(); - // TODO: support unicode here - key = tolower(key); + int32 count = fShortcuts.CountItems(); + + key = Shortcut::PrepareKey(key); + modifiers = Shortcut::PrepareModifiers(modifiers); for (int32 index = 0; index < count; index++) { - _BCmdKey *cmdKey = (_BCmdKey *)accelList.ItemAt(index); + Shortcut *shortcut = (Shortcut *)fShortcuts.ItemAt(index); - if (cmdKey->key == key && cmdKey->modifiers == modifiers) - return index; + if (shortcut->Matches(key, modifiers)) + return shortcut; } - return -1; + return NULL; } @@ -2622,7 +2669,7 @@ BView * BWindow::_FindNextNavigable(BView *focus, uint32 flags) { if (focus == NULL) - focus = top_view; + focus = fTopView; BView *nextFocus = focus; @@ -2636,7 +2683,7 @@ BWindow::_FindNextNavigable(BView *focus, uint32 flags) while (!nextFocus->fNextSibling && nextFocus->fParent) nextFocus = nextFocus->fParent; - if (nextFocus == top_view) + if (nextFocus == fTopView) nextFocus = nextFocus->fFirstChild; else nextFocus = nextFocus->fNextSibling; @@ -2669,7 +2716,7 @@ BWindow::_FindPreviousNavigable(BView *focus, uint32 flags) while (!prevFocus->fPreviousSibling && prevFocus->fParent) prevFocus = prevFocus->fParent; - if (prevFocus == top_view) + if (prevFocus == fTopView) prevFocus = findLastChild(prevFocus); else prevFocus = prevFocus->fPreviousSibling; @@ -2704,7 +2751,7 @@ void BWindow::drawAllViews(BView* aView) { if (Lock()) { - top_view->Invalidate(); + fTopView->Invalidate(); Unlock(); } Sync(); @@ -2797,7 +2844,7 @@ BWindow::PrintToStream() const Flags = %lx\ send_port = %ld\ receive_port = %ld\ - top_view name = %s\ + fTopView name = %s\ focus view name = %s\ lastMouseMoved = %s\ fLink = %p\ @@ -2812,13 +2859,13 @@ BWindow::PrintToStream() const fFlags, fLink->SenderPort(), fLink->ReceiverPort(), - top_view != NULL ? top_view->Name() : "NULL", + fTopView != NULL ? fTopView->Name() : "NULL", fFocus != NULL ? fFocus->Name() : "NULL", fLastMouseMovedView != NULL ? fLastMouseMovedView->Name() : "NULL", fLink, fKeyMenuBar != NULL ? fKeyMenuBar->Name() : "NULL", fDefaultButton != NULL ? fDefaultButton->Name() : "NULL", - accelList.CountItems()); + fShortcuts.CountItems()); /* for( int32 i=0; i