|
From: Ralph T. <ra...@us...> - 2005-04-05 05:46:14
|
Update of /cvsroot/adobe-source/sandbox/adobe-source/adobe/test/visual/sources/win In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1814/adobe-source/adobe/test/visual/sources/win Modified Files: main.cpp ui_core_implementation.cpp Added Files: event_dispatcher.cpp Log Message: The event_dispatcher has moved out of the ui_core_implementation.cpp file. The main message pump now checks for modifier keys whenever an event is recieved. All modifier keys now work on Windows. Index: main.cpp =================================================================== RCS file: /cvsroot/adobe-source/sandbox/adobe-source/adobe/test/visual/sources/win/main.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** main.cpp 23 Mar 2005 18:52:00 -0000 1.2 --- main.cpp 5 Apr 2005 05:46:05 -0000 1.3 *************** *** 7,10 **** --- 7,11 ---- #include "express_viewer.hpp" + #include "event_dispatcher.hpp" #include "report_exception.hpp" *************** *** 112,115 **** --- 113,124 ---- while ( GetMessage( &msg, 0, 0, 0 ) ) { + // + // Push every message through the event_dispatcher, in case it is a keyboard + // modifier. + // + event_dispatcher::keyboard(msg.message, msg.wParam); + // + // We always pass every message though to the application anyway. + // TranslateMessage( &msg ); DispatchMessage( &msg ); --- NEW FILE: event_dispatcher.cpp --- /* Copyright 2005 Ralph Thomas Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /****************************************************************************************************/ #include "event_dispatcher.hpp" #include "ui_core_implementation.hpp" #include <adobe/future/enum_ops.hpp> #include <sstream> /****************************************************************************************************/ adobe::modifiers_t convert_modifiers(ULONG os_modifiers) { adobe::modifiers_t result(adobe::modifiers_none_s); #define MAPMOD(osmod, adobemod) if (os_modifiers == (osmod)) result = result | (adobemod) // // Note that VK_MENU is the ALT key, and that VK_APPS is the "popup menu" key. // If I plug my keyboard into a Mac then the Windows-logo key becomes the Apple // key (also called the command key). However, the Windows-logo key brings up // the start menu, so I'm using the "popup menu" key for command instead. // MAPMOD(VK_CAPITAL, adobe::modifiers_caps_lock_s); MAPMOD(VK_CONTROL, adobe::modifiers_any_control_s); MAPMOD(VK_SHIFT, adobe::modifiers_any_shift_s); MAPMOD(VK_MENU, adobe::modifiers_any_option_s); MAPMOD(VK_APPS, adobe::modifiers_any_command_s); return result; } /****************************************************************************************************/ namespace adobe { /****************************************************************************************************/ // /// This is the global single instance of the event_dispatcher, and it's /// reference count. // static event_dispatcher* event_singleton_g = 0; static unsigned int event_refcount_g = 0; /****************************************************************************************************/ event_dispatcher::event_dispatcher() : current_id_m(1000) { } /****************************************************************************************************/ LRESULT event_dispatcher::event(UINT message, WPARAM wParam, LPARAM lParam, bool& handled) { handled = false; // // Let's first ensure that we actually have an event_dispatcher to work // on. // if (!event_refcount_g) return 0; // // The child id is usually the low word of the wParam. // control_map_t& cmap(event_singleton_g->control_map_m); control_map_t::iterator control = cmap.find(LOWORD(wParam)); if (control == cmap.end()) return 0; // // We found something to invoke, so we claim that we handled the message // and return the value of the control's event method. // handled = true; return control->second->event(message, wParam, lParam); } /****************************************************************************************************/ void event_dispatcher::keyboard(UINT message, WPARAM wParam) { // // Verify that this is a keyboard message which could contain // modifiers. // if ((message != WM_KEYDOWN) && (message != WM_KEYUP) && (message != WM_SYSKEYDOWN) && (message != WM_SYSKEYUP)) return; // // Ensure that we have an event_dispatcher to work on. // if (!event_refcount_g) return; // // Look up the modifiers which this event translates to. If they // have changed since the last time then we can tell the controls // about it. // static modifiers_t previous_modifiers(modifiers_none_s); // // This is the modifier which corresponds to the key which was // just pressed or released. // modifiers_t the_modifier(convert_modifiers(wParam)); modifiers_t current_modifiers(previous_modifiers); // // Now we need to either add or remove the current modifier // from the previous modifiers. // if ((message == WM_KEYDOWN) || (message == WM_SYSKEYDOWN)) current_modifiers |= the_modifier; else current_modifiers &= ~the_modifier; // // Only dispatch to all of the children if the currently // pressed modifiers has changed. // if (previous_modifiers != current_modifiers) { // // Iterate through all of the controls and tell them of // the new modifier state. // control_map_t::iterator first = event_singleton_g->control_map_m.begin(); control_map_t::iterator last = event_singleton_g->control_map_m.end(); while (first != last) { first->second->modify(current_modifiers); first++; } } previous_modifiers = current_modifiers; } /****************************************************************************************************/ event_dispatcher::reference::reference() : child_id_m(-1) { // // If the reference count is zero then we have to allocate a new // event dispatcher. // if (!event_refcount_g) event_singleton_g = new event_dispatcher(); event_refcount_g++; } /****************************************************************************************************/ event_dispatcher::reference::~reference() { // // If we subscribed a control then it will be in the map, we // must remove that mapping so that events don't get sent there // any more. // event_dispatcher::control_map_t::iterator us = event_singleton_g->control_map_m.find(child_id_m); if (us != event_singleton_g->control_map_m.end()) event_singleton_g->control_map_m.erase(us); // // Decrease the reference count and delete the event_dispatcher // if there are no remaining references. // event_refcount_g--; if (!event_refcount_g) { delete event_singleton_g; event_singleton_g = 0; } } /****************************************************************************************************/ HMENU event_dispatcher::reference::subscribe(control_t* control) { // // If we're not given a control then we have nothing to subscribe. // if (!control) return 0; // // Store the child ID we're going to use, so that child_id can return it. // child_id_m = event_singleton_g->current_id_m++; event_singleton_g->control_map_m[child_id_m] = control; return (HMENU)child_id_m; } /****************************************************************************************************/ HMENU event_dispatcher::reference::child_id() const { return (HMENU)child_id_m; } /****************************************************************************************************/ } /****************************************************************************************************/ Index: ui_core_implementation.cpp =================================================================== RCS file: /cvsroot/adobe-source/sandbox/adobe-source/adobe/test/visual/sources/win/ui_core_implementation.cpp,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** ui_core_implementation.cpp 4 Apr 2005 23:32:25 -0000 1.9 --- ui_core_implementation.cpp 5 Apr 2005 05:46:05 -0000 1.10 *************** *** 79,103 **** /****************************************************************************************************/ - adobe::modifiers_t convert_modifiers(ULONG os_modifiers) - { - adobe::modifiers_t result(adobe::modifiers_none_s); - - #define MAPMOD(osmod, adobemod) if ((os_modifiers & (osmod)) == (osmod)) result |= (adobemod) - - MAPMOD(VK_CAPITAL, adobe::modifiers_caps_lock_s); - MAPMOD(VK_LMENU, adobe::modifiers_any_command_s); - MAPMOD(VK_LSHIFT, adobe::modifiers_left_shift_s); - MAPMOD(VK_LWIN, adobe::modifiers_left_option_s); - MAPMOD(VK_LCONTROL, adobe::modifiers_left_control_s); - MAPMOD(VK_RMENU, adobe::modifiers_any_command_s); - MAPMOD(VK_RSHIFT, adobe::modifiers_right_shift_s); - MAPMOD(VK_RWIN, adobe::modifiers_right_option_s); - MAPMOD(VK_RCONTROL, adobe::modifiers_right_control_s); - - return result; - } - - /****************************************************************************************************/ - namespace hackery { --- 79,82 ---- *************** *** 1069,1219 **** /****************************************************************************************************/ // - /// This class's job is to keep track of control_t instances, and the windows which they - /// own. It keeps track of them all in order to dispatch events to them in a safe manner - /// (safer than assuming the user data section of HWND is a pointer into this address space). - /// It works by issuing out sequential numbers which are used by CreateWindow as the HMENU - /// value (which is LPARAM on all incoming events). - /// - /// This class is a reference counted singleton. It is acquired via inc_ref and released - /// via dec_ref. - // - // REVISIT (ralpht): The event_dispatcher singleton+refcounted mechanism is very crude, - // it should be expanded into something more generic, as various other objects - // probably follow the same pattern. - // - class event_dispatcher - { - typedef std::map<int, control_t*> control_map_t; - - control_map_t control_map_m; ///< The control_map_m contains the mapping from HMENU value to control_t. - int current_value_m;///< The current HMENU value to assign. - static int ref_count_m; ///< The reference count. - static event_dispatcher* instance_m; ///< Our instance. - // - /// The constructor is private to enforce the singleton nature - /// of this class. - // - event_dispatcher() : current_value_m(1000) {} - public: - // - /// Return the single instance of this class. This is the only way - /// to get a valid reference to the event_dispatcher. This reference - /// must be released with dec_ref. - /// - /// \return a reference to the single instance of this class. - /// \sa dec_ref - // - static event_dispatcher& inc_ref() - { - if (ref_count_m == 0) - { - instance_m = new event_dispatcher; - } - ref_count_m++; - return *instance_m; - } - // - /// Release this event dispatcher reference. - // - void dec_ref() - { - ref_count_m--; - if (ref_count_m == 0) - { - delete instance_m; - instance_m = 0; - } - } - // - /// Return a number to use as the new window's child ID - /// and associate the returned number with the given control. - /// - /// \param control the control to associate with the number - /// which will be returned. - /// \return the number to use as the child ID in CreateWindow. - // - HMENU subscribe(control_t* control) - { - // - // Make sure that we actually have a control! - // - if (!control) return 0; - // - // Associate the values and return the child ID. - control_map_m[current_value_m] = control; - return (HMENU)current_value_m++; - } - // - /// Remove the association to the given control, such that - /// it will never be called into unless it subscribes and - /// creates a new window. - /// - /// Typically this function is called before a control is - /// deleted. - /// - /// \param control the control to never call again. - // - void unsubscribe(const control_t* control) - { - control_map_t::iterator first = control_map_m.begin(); - control_map_t::iterator last = control_map_m.end(); - while (first != last) - { - if (first->second == control) - { - control_map_m.erase(first); - return; - } - first++; - } - } - // - /// Try to propagate an event out to an individual child window. - /// - /// \param message the Windows event type. - /// \param wParam the pointer parameter. - /// \param lParam the integer parameter, usually the child ID. - /// \param handled set to true if a matching child was found, - /// false otherwise. - /// - /// \return the event return code, from the widget's event method. - // - LRESULT event(UINT message, WPARAM wParam, LPARAM lParam, bool& handled) - { - handled = false; - // - // Normally the child id is the low word of the wParam. - // - int id = LOWORD(wParam); - control_map_t::iterator control = control_map_m.find(id); - if(control == control_map_m.end()) return 0; - // - // Invoke the event handler. - // - handled = true; - return control->second->event(message, wParam, lParam); - } - // - /// Inform all controls that a modifier key has been pressed or - /// released. - /// - /// \param modifiers the modifier key combination currently pressed. - // - void modify(modifiers_t modifiers) - { - // - // Iterate through all of the controls. - // - // REVISIT (ralpht): Use for_each, and some kind of functor compose here. - // - for(control_map_t::iterator i = control_map_m.begin(); i != control_map_m.end(); i++) - i->second->modify(modifiers); - } - }; - int event_dispatcher::ref_count_m = 0; - event_dispatcher* event_dispatcher::instance_m = 0; - - /****************************************************************************************************/ - // /// This function encapsulates the logic for deciding if a message should be /// sent to the event_dispatcher for submission to child windows. If the --- 1048,1051 ---- *************** *** 1226,1262 **** { handled = false; if ((message == WM_COMMAND) || (message == WM_NOTIFY)) ! { ! event_dispatcher& ed = event_dispatcher::inc_ref(); ! LRESULT rv = ed.event(message, wParam, lParam, handled); ! ed.dec_ref(); ! return rv; ! } ! else if (message == WM_KEYDOWN || message == WM_KEYUP) ! { ! // ! // This might be a notifier event. We never claim to ! // handle key events, as the destination control may ! // require them for something else. ! // ! static modifiers_t previous_modifiers(modifiers_none_s); ! modifiers_t current_modifiers(convert_modifiers(wParam)); ! // ! // If the current modifiers are different from the ! // previous ones then tell all of the controls about ! // it. ! // ! if (current_modifiers != previous_modifiers) ! { ! event_dispatcher& ed(event_dispatcher::inc_ref()); ! ed.modify(current_modifiers); ! ed.dec_ref(); ! } ! // ! // Make sure that we always compare against the previous ! // modifiers. ! // ! previous_modifiers = previous_modifiers; ! } return 0; } --- 1058,1067 ---- { handled = false; + // + // We let event_dispatcher::event set handled either way if we determine + // that this event is suitable for controls. + // if ((message == WM_COMMAND) || (message == WM_NOTIFY)) ! return event_dispatcher::event(message, wParam, lParam, handled); return 0; } *************** *** 1625,1629 **** control_t::control_t() : control_m(0), uxtheme_type_m(0), theme_m(theme_default_s), default_window_proc_m(0), ! event_dispatcher_m(event_dispatcher::inc_ref()), child_id_m(0) #ifndef NDEBUG , placed_m(false) --- 1430,1434 ---- control_t::control_t() : control_m(0), uxtheme_type_m(0), theme_m(theme_default_s), default_window_proc_m(0), ! child_id_m(0) #ifndef NDEBUG , placed_m(false) *************** *** 1673,1677 **** control_t::control_t(const control_t& rhs) : control_m(0), uxtheme_type_m(0), theme_m(rhs.theme_m), default_window_proc_m(0), ! event_dispatcher_m(event_dispatcher::inc_ref()), child_id_m(0) #ifndef NDEBUG , placed_m(false) --- 1478,1482 ---- control_t::control_t(const control_t& rhs) : control_m(0), uxtheme_type_m(0), theme_m(rhs.theme_m), default_window_proc_m(0), ! child_id_m(0) #ifndef NDEBUG , placed_m(false) *************** *** 1689,1696 **** { // - // Make sure that we no longer get events delivered here. - // - event_dispatcher_m.unsubscribe(this); - // // Set the window procedure back to it's original value so that the // User32 internal data can be freed. --- 1494,1497 ---- *************** *** 1703,1710 **** if (::GetParent(control_m) == 0) ::DestroyWindow(control_m); - // - // Release our event_dispatcher reference. - // - event_dispatcher_m.dec_ref(); } --- 1504,1507 ---- |