include/vcl/debugevent.hxx | 36 ++++ include/vcl/window.hxx | 3 vcl/Library_vcl.mk | 1 vcl/source/app/svmain.cxx | 5 vcl/source/window/debugevent.cxx | 281 +++++++++++++++++++++++++++++++++++++++ vcl/source/window/window.cxx | 12 + 6 files changed, 338 insertions(+)
New commits: commit 344dc7fd0684acc31f4c18e99e65bfa6700c9c64 Author: Michael Meeks <michael.me...@collabora.com> Date: Thu May 8 21:59:45 2014 +0100 Make the inserted text more European and sensible for now. Change-Id: I8b2ecef11362c0fc1dc2b76780140881e769bb89 diff --git a/include/vcl/debugevent.hxx b/include/vcl/debugevent.hxx index ce31570..2700324 100644 --- a/include/vcl/debugevent.hxx +++ b/include/vcl/debugevent.hxx @@ -20,7 +20,7 @@ class VCL_DLLPUBLIC DebugEventInjector : Timer { DebugEventInjector( sal_uInt32 nMaxEvents ); Window *ChooseWindow(); - void InjectKeyEvent(); + void InjectTextEvent(); void InjectMenuEvent(); void InjectMouseEvent(); void InjectEvent(); diff --git a/vcl/source/window/debugevent.cxx b/vcl/source/window/debugevent.cxx index 37ca716..e83909e 100644 --- a/vcl/source/window/debugevent.cxx +++ b/vcl/source/window/debugevent.cxx @@ -7,7 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <stdio.h> +// #include <stdio.h> #include <rtl/math.hxx> #include <rtl/string.hxx> #include <tools/time.hxx> @@ -110,11 +110,11 @@ void DebugEventInjector::InjectMenuEvent() SalMenuEvent aEvent = aIds[ getRandom() * aIds.size() ]; bool bHandled = ImplWindowFrameProc( pSysWin, NULL, nEvent, &aEvent); - fprintf( stderr, "Injected menu event %p (%d) '%s' -> %d\n", +/* fprintf( stderr, "Injected menu event %p (%d) '%s' -> %d\n", aEvent.mpMenu, aEvent.mnId, OUStringToOString( ((Menu *)aEvent.mpMenu)->GetItemText( aEvent.mnId ), RTL_TEXTENCODING_UTF8 ).getStr(), - (int)bHandled); + (int)bHandled); */ } static void InitKeyEvent( SalKeyEvent &rKeyEvent ) @@ -131,22 +131,43 @@ static void InitKeyEvent( SalKeyEvent &rKeyEvent ) rKeyEvent.mnRepeat = 0; } -void DebugEventInjector::InjectKeyEvent() +void DebugEventInjector::InjectTextEvent() { SalKeyEvent aKeyEvent; Window *pWindow = ChooseWindow(); InitKeyEvent( aKeyEvent ); - sal_uInt16 nCode = getRandom() * KEY_CODE; - if( getRandom() < 0.05 ) // modifier - nCode |= (sal_uInt16)( getRandom() * KEY_MODTYPE ) & KEY_MODTYPE; - aKeyEvent.mnCode = nCode; - aKeyEvent.mnCharCode = getRandom() * 0xffff; + if (getRandom() < 0.10) // Occasionally a truly random event + { + aKeyEvent.mnCode = getRandom() * KEY_CODE; + aKeyEvent.mnCharCode = getRandom() * 0xffff; + } + else + { + struct { + sal_uInt16 nCodeStart, nCodeEnd; + char aCharStart; + } nTextCodes[] = { + { KEY_0, KEY_9, '0' }, + { KEY_A, KEY_Z, 'a' } + }; + + size_t i = getRandom() * SAL_N_ELEMENTS( nTextCodes ); + int offset = trunc( getRandom() * ( nTextCodes[i].nCodeEnd - nTextCodes[i].nCodeStart ) ); + aKeyEvent.mnCode = nTextCodes[i].nCodeStart + offset; + aKeyEvent.mnCharCode = nTextCodes[i].aCharStart + offset; +// fprintf( stderr, "Char '%c' offset %d into record %d base '%c'\n", +// aKeyEvent.mnCharCode, offset, (int)i, nTextCodes[i].aCharStart ); + } + + if( getRandom() < 0.05 ) // modifier + aKeyEvent.mnCode |= (sal_uInt16)( getRandom() * KEY_MODTYPE ) & KEY_MODTYPE; bool bHandled = ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYINPUT, &aKeyEvent); - fprintf (stderr, "Injected key 0x%x -> %d win %p\n", - (int) aKeyEvent.mnCode, (int)bHandled, pWindow); +// fprintf( stderr, "Injected key 0x%x -> %d win %p\n", +// (int) aKeyEvent.mnCode, (int)bHandled, pWindow ); + ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYUP, &aKeyEvent ); } /* @@ -155,12 +176,14 @@ void DebugEventInjector::InjectKeyEvent() */ void DebugEventInjector::InjectEvent() { +// fprintf( stderr, "%6d - ", (int)mnEventsLeft ); + double nRand = getRandom(); - if (nRand < 0.50) + if (nRand < 0.30) { int nEvents = getRandom() * 10; for (int i = 0; i < nEvents; i++) - InjectKeyEvent(); + InjectTextEvent(); } else if (nRand < 0.60) InjectKeyNavEdit(); @@ -222,8 +245,8 @@ void DebugEventInjector::InjectKeyNavEdit() aKeyEvent.mnCharCode = 0x0; // hopefully unused. bool bHandled = ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYINPUT, &aKeyEvent ); - fprintf( stderr, "Injected edit / move key 0x%x -> %d win %p\n", - (int) aKeyEvent.mnCode, (int)bHandled, pWindow ); +// fprintf( stderr, "Injected edit / move key 0x%x -> %d win %p\n", +// (int) aKeyEvent.mnCode, (int)bHandled, pWindow ); ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYUP, &aKeyEvent ); } commit 45935fc3fed0a215e93de20c28933bf318f618cd Author: Michael Meeks <michael.me...@collabora.com> Date: Thu May 8 21:43:46 2014 +0100 quit after emitting all the events to allow valgrinding. Change-Id: Ibee9d8f00008dd0a266db276772d48deb0bd9d18 diff --git a/vcl/source/window/debugevent.cxx b/vcl/source/window/debugevent.cxx index 2f37678..37ca716 100644 --- a/vcl/source/window/debugevent.cxx +++ b/vcl/source/window/debugevent.cxx @@ -120,7 +120,7 @@ void DebugEventInjector::InjectMenuEvent() static void InitKeyEvent( SalKeyEvent &rKeyEvent ) { double nRand = getRandom(); - if (nRand < 0.01) + if (nRand < 0.001) rKeyEvent.mnTime = getRandom() * ULONG_MAX; else rKeyEvent.mnTime = Time::GetSystemTicks(); @@ -216,14 +216,15 @@ void DebugEventInjector::InjectKeyNavEdit() InitKeyEvent( aKeyEvent ); aKeyEvent.mnCode = nKey; - if (getRandom() < 0.10) // modifier + if (getRandom() < 0.15) // modifier aKeyEvent.mnCode |= (sal_uInt16)(getRandom() * KEY_MODTYPE) & KEY_MODTYPE; aKeyEvent.mnCharCode = 0x0; // hopefully unused. - bool bHandled = ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYINPUT, &aKeyEvent); - fprintf (stderr, "Injected edit / move key 0x%x -> %d win %p\n", - (int) aKeyEvent.mnCode, (int)bHandled, pWindow); + bool bHandled = ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYINPUT, &aKeyEvent ); + fprintf( stderr, "Injected edit / move key 0x%x -> %d win %p\n", + (int) aKeyEvent.mnCode, (int)bHandled, pWindow ); + ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYUP, &aKeyEvent ); } void DebugEventInjector::Timeout() @@ -235,6 +236,8 @@ void DebugEventInjector::Timeout() SetTimeout( 1 ); Start(); } + else + Application::Quit(); } DebugEventInjector *DebugEventInjector::getCreate() commit 4ea70f09e964fd39b46941313493a11e131e21e1 Author: Michael Meeks <michael.me...@collabora.com> Date: Thu May 8 17:03:08 2014 +0100 Initial cut at some infinite monkeys work. Change-Id: I71c7fe027262305893d8eabee94a726f4aa909d6 diff --git a/include/vcl/debugevent.hxx b/include/vcl/debugevent.hxx new file mode 100644 index 0000000..ce31570 --- /dev/null +++ b/include/vcl/debugevent.hxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_VCL_DEBUGEVENT_HXX +#define INCLUDED_VCL_DEBUGEVENT_HXX + +#include <vcl/dllapi.h> +#include <vcl/timer.hxx> +#include <sal/types.h> +#include <vcl/window.hxx> + +class VCL_DLLPUBLIC DebugEventInjector : Timer { + sal_uInt32 mnEventsLeft; + DebugEventInjector( sal_uInt32 nMaxEvents ); + + Window *ChooseWindow(); + void InjectKeyEvent(); + void InjectMenuEvent(); + void InjectMouseEvent(); + void InjectEvent(); + void InjectKeyNavEdit(); + virtual void Timeout(); + + public: + static DebugEventInjector *getCreate(); +}; + +#endif // INCLUDED_VCL_DEBUGEVENT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx index c9f8390..4576bdb 100644 --- a/include/vcl/window.hxx +++ b/include/vcl/window.hxx @@ -1029,6 +1029,9 @@ public: void SetData( void* pNewData ); void* GetData() const; + /// Add all children to @rAllChildren recursively. + SAL_DLLPRIVATE void CollectChildren(::std::vector<Window *>& rAllChildren ); + void ShowFocus( const Rectangle& rRect ); void HideFocus(); diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 4e53256..e321525 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -116,6 +116,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/window/builder \ vcl/source/window/cmdevt \ vcl/source/window/cursor \ + vcl/source/window/debugevent \ vcl/source/window/decoview \ vcl/source/window/dialog \ vcl/source/window/dlgctrl \ diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx index f5b05fe..25c8f99 100644 --- a/vcl/source/app/svmain.cxx +++ b/vcl/source/app/svmain.cxx @@ -37,6 +37,7 @@ #include "vcl/configsettings.hxx" #include "vcl/lazydelete.hxx" #include "vcl/embeddedfontshelper.hxx" +#include "vcl/debugevent.hxx" #ifdef WNT #include <svsys.h> @@ -288,6 +289,10 @@ bool InitVCL() DBGGUI_INIT_SOLARMUTEXCHECK(); +#if OSL_DEBUG_LEVEL > 0 + DebugEventInjector::getCreate(); +#endif + return true; } diff --git a/vcl/source/window/debugevent.cxx b/vcl/source/window/debugevent.cxx new file mode 100644 index 0000000..2f37678 --- /dev/null +++ b/vcl/source/window/debugevent.cxx @@ -0,0 +1,255 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <stdio.h> +#include <rtl/math.hxx> +#include <rtl/string.hxx> +#include <tools/time.hxx> +#include <vcl/keycodes.hxx> +#include <vcl/svapp.hxx> +#include <vcl/debugevent.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/menu.hxx> +#include "window.h" +#include "salwtype.hxx" + +#if OSL_DEBUG_LEVEL > 0 + +DebugEventInjector::DebugEventInjector( sal_uInt32 nMaxEvents) : + mnEventsLeft( nMaxEvents ) +{ + SetTimeout( 1000 /* ms */ ); + Start(); +} + +static double getRandom() +{ + return (double)rand() / RAND_MAX; +} + +Window *DebugEventInjector::ChooseWindow() +{ + Window *pWindow, *pParent; + + if (getRandom() < 0.80 && + (pWindow = Application::GetFocusWindow())) + return pWindow; + + if (getRandom() > 0.50 || + !(pParent = Application::GetActiveTopWindow())) + { + // select a top window at random + long nIdx = Application::GetTopWindowCount() * getRandom(); + if (!(pParent = Application::GetTopWindow( nIdx ))) + pParent = static_cast<Window *>(Application::GetAppWindow()); + } + assert (pParent != NULL); + + std::vector< Window *> aChildren; + pParent->CollectChildren( aChildren ); + + return aChildren[ aChildren.size() * getRandom() ]; +} + +void DebugEventInjector::InjectMouseEvent() +{ +} + +typedef std::vector< SalMenuEvent > MenuItemIds; + +static void CollectMenuItemIds( Menu *pMenu, MenuItemIds &rIds ) +{ + sal_uInt16 nItems = pMenu->GetItemCount(); + for (sal_uInt16 i = 0; i < nItems; i++) + { + if (pMenu->GetItemType( i ) != MENUITEM_SEPARATOR || getRandom() < 0.01) + rIds.push_back( SalMenuEvent( pMenu->GetItemId( i ), pMenu ) ); + PopupMenu *pPopup = pMenu->GetPopupMenu( i ); + if (pPopup) + CollectMenuItemIds( pPopup, rIds ); + } +} + +void DebugEventInjector::InjectMenuEvent() +{ + Window *pFocus = Application::GetFocusWindow(); + if (!pFocus) + return; + + SystemWindow *pSysWin = pFocus->GetSystemWindow(); + if (!pSysWin) + return; + + MenuBar *pMenuBar = pSysWin->GetMenuBar(); + if (!pMenuBar) + return; + + sal_uInt16 nEvents[] = { + SALEVENT_MENUCOMMAND, + SALEVENT_MENUCOMMAND, + SALEVENT_MENUACTIVATE, + SALEVENT_MENUDEACTIVATE, + SALEVENT_MENUHIGHLIGHT, + SALEVENT_MENUCOMMAND, + SALEVENT_MENUCOMMAND, + SALEVENT_MENUCOMMAND, + SALEVENT_MENUBUTTONCOMMAND, + SALEVENT_MENUBUTTONCOMMAND, + }; + + MenuItemIds aIds; + CollectMenuItemIds( pMenuBar, aIds ); + + sal_uInt16 nEvent = nEvents[ (int)(getRandom() * SAL_N_ELEMENTS( nEvents )) ]; + SalMenuEvent aEvent = aIds[ getRandom() * aIds.size() ]; + bool bHandled = ImplWindowFrameProc( pSysWin, NULL, nEvent, &aEvent); + + fprintf( stderr, "Injected menu event %p (%d) '%s' -> %d\n", + aEvent.mpMenu, aEvent.mnId, + OUStringToOString( ((Menu *)aEvent.mpMenu)->GetItemText( aEvent.mnId ), + RTL_TEXTENCODING_UTF8 ).getStr(), + (int)bHandled); +} + +static void InitKeyEvent( SalKeyEvent &rKeyEvent ) +{ + double nRand = getRandom(); + if (nRand < 0.01) + rKeyEvent.mnTime = getRandom() * ULONG_MAX; + else + rKeyEvent.mnTime = Time::GetSystemTicks(); + + if (getRandom() < 0.01) + rKeyEvent.mnRepeat = getRandom() * 20; + else + rKeyEvent.mnRepeat = 0; +} + +void DebugEventInjector::InjectKeyEvent() +{ + SalKeyEvent aKeyEvent; + Window *pWindow = ChooseWindow(); + + InitKeyEvent( aKeyEvent ); + sal_uInt16 nCode = getRandom() * KEY_CODE; + if( getRandom() < 0.05 ) // modifier + nCode |= (sal_uInt16)( getRandom() * KEY_MODTYPE ) & KEY_MODTYPE; + + aKeyEvent.mnCode = nCode; + aKeyEvent.mnCharCode = getRandom() * 0xffff; + + bool bHandled = ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYINPUT, &aKeyEvent); + fprintf (stderr, "Injected key 0x%x -> %d win %p\n", + (int) aKeyEvent.mnCode, (int)bHandled, pWindow); +} + +/* + * The more heuristics we have to inform this the better, + * key-bindings, menu entries, allowable entry types etc. + */ +void DebugEventInjector::InjectEvent() +{ + double nRand = getRandom(); + if (nRand < 0.50) + { + int nEvents = getRandom() * 10; + for (int i = 0; i < nEvents; i++) + InjectKeyEvent(); + } + else if (nRand < 0.60) + InjectKeyNavEdit(); + else if (nRand < 0.95) + InjectMenuEvent(); + else + InjectMouseEvent(); +} + +void DebugEventInjector::InjectKeyNavEdit() +{ + Window *pWindow = ChooseWindow(); + + struct { + double mnProb; + sal_uInt16 mnKey; + } nWeights[] = { + // edit / escape etc. - 50% + { 0.20, KEY_SPACE }, + { 0.10, KEY_TAB }, + { 0.07, KEY_RETURN }, + { 0.05, KEY_DELETE }, + { 0.05, KEY_BACKSPACE }, + + // navigate - 45% + { 0.15, KEY_LEFT }, + { 0.10, KEY_RIGHT }, + { 0.05, KEY_UP }, + { 0.05, KEY_DOWN }, + { 0.05, KEY_PAGEUP }, + { 0.05, KEY_PAGEDOWN }, + + // other + { 0.01, KEY_INSERT }, + { 0.02, KEY_HOME }, + { 0.02, KEY_END }, + }; + + double d = 0.0, nRand = getRandom(); + sal_uInt16 nKey = KEY_SPACE; + for ( size_t i = 0; i < SAL_N_ELEMENTS( nWeights ); ++i ) + { + d += nWeights[i].mnProb; + assert (d < 1.01); + if ( nRand < d ) + { + nKey = nWeights[i].mnKey; + break; + } + } + + SalKeyEvent aKeyEvent; + InitKeyEvent( aKeyEvent ); + aKeyEvent.mnCode = nKey; + + if (getRandom() < 0.10) // modifier + aKeyEvent.mnCode |= (sal_uInt16)(getRandom() * KEY_MODTYPE) & KEY_MODTYPE; + + aKeyEvent.mnCharCode = 0x0; // hopefully unused. + + bool bHandled = ImplWindowFrameProc( pWindow, NULL, SALEVENT_KEYINPUT, &aKeyEvent); + fprintf (stderr, "Injected edit / move key 0x%x -> %d win %p\n", + (int) aKeyEvent.mnCode, (int)bHandled, pWindow); +} + +void DebugEventInjector::Timeout() +{ + InjectEvent(); + mnEventsLeft--; + if (mnEventsLeft > 0) + { + SetTimeout( 1 ); + Start(); + } +} + +DebugEventInjector *DebugEventInjector::getCreate() +{ + sal_uInt32 nEvents; + const char *pEvents = getenv("VCL_EVENT_INJECTION"); + if (!pEvents) + return NULL; + nEvents = OString( pEvents ).toUInt32(); + if (nEvents > 0) + return new DebugEventInjector( nEvents ); + else + return NULL; +} + +#endif // OSL_DEBUG_LEVEL > 0 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index b77447c..849bce6 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -4727,6 +4727,18 @@ void Window::NotifyAllChildren( DataChangedEvent& rDCEvt ) } } +void Window::CollectChildren(::std::vector<Window *>& rAllChildren ) +{ + rAllChildren.push_back( this ); + + Window* pChild = mpWindowImpl->mpFirstChild; + while ( pChild ) + { + pChild->CollectChildren( rAllChildren ); + pChild = pChild->mpWindowImpl->mpNext; + } +} + void Window::SetPointFont( const Font& rFont ) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits