x11uitoolkit.cpp

来自「这是VCF框架的代码」· C++ 代码 · 共 2,479 行 · 第 1/4 页

CPP
2,479
字号
//X11UIToolkit.cpp/*Copyright 2000-2004 The VCF Project.Please see License.txt in the top level directorywhere you installed the VCF.*/#include "vcf/ApplicationKit/ApplicationKit.h"#include "vcf/ApplicationKit/ApplicationKitPrivate.h"#include "vcf/ApplicationKit/X11UIToolkit.h"#include "vcf/ApplicationKit/X11Desktop.h"#include "vcf/ApplicationKit/X11Application.h"#include "vcf/ApplicationKit/X11Control.h"#include "vcf/ApplicationKit/X11Window.h"#include "vcf/ApplicationKit/X11ControlContext.h"#include "vcf/ApplicationKit/X11Cursor.h"#include "vcf/ApplicationKit/LightweightComponent.h"#include "vcf/ApplicationKit/X11Dialog.h"#include "vcf/ApplicationKit/X11SimpleTextControl.h"#include <signal.h>#include <X11/keysym.h>#include <X11/Xproto.h>#define X_KEYBUFFER_SIZE	100//get rid of the stupip fscking warning from GCC#define NULL 0using namespace VCF;//UIMetricsManager implementation for X11class X11UIMetricsManager : public UIMetricsManager {public:	X11UIMetricsManager(){}	virtual ~X11UIMetricsManager(){}	virtual VCF::Font getDefaultFontFor( const UIMetricsManager::FontType& type ) {		VCF::Font result("ARIAL", 10);		switch ( type ) {			case UIMetricsManager::ftMenuItemFont : {			}			break;			case UIMetricsManager::ftSelectedMenuItemFont : {			}			break;			case UIMetricsManager::ftControlFont :  case UIMetricsManager::ftSystemFont : {			}			break;			case UIMetricsManager::ftMessageFont : {			}			break;			case UIMetricsManager::ftToolTipFont : {			}			break;		}		return result;	}	virtual double getDefaultHeightFor( const UIMetricsManager::HeightType& type )  {		double result = 0.0;		switch ( type ) {			case UIMetricsManager::htLabelHeight : {				VCF::Font f = getDefaultFontFor( UIMetricsManager::ftControlFont );				result = f.getHeight() * 1.75;			}			break;			case UIMetricsManager::htComboBoxHeight : {				VCF::Font f = getDefaultFontFor( UIMetricsManager::ftControlFont );				result = f.getHeight() * 2.0;			}			break;			case UIMetricsManager::htListItemHeight : {				VCF::Font f = getDefaultFontFor( UIMetricsManager::ftControlFont );				result = f.getHeight() * 1.65;			}			break;			case UIMetricsManager::htButtonHeight : {				VCF::Font f = getDefaultFontFor( UIMetricsManager::ftControlFont );				result = (f.getHeight() * 1.75) + 2.50;			}			break;			case UIMetricsManager::htRadioBoxHeight : case UIMetricsManager::htCheckBoxHeight : {				//in Win32 a radio box or check box is ALWAYS 10 dialog units high				//dialog units are converted by				//(2 * average char height dialog font / average char height system font pixels				//where average char height dialog font = TEXTMETRIC.tmHeight field or a Font::getHeight()				VCF::Font f = getDefaultFontFor( UIMetricsManager::ftControlFont );				result = (9.0 * ((2.0 * f.getHeight()) / f.getHeight())) - 4.0;//0.590909;			}			break;			case UIMetricsManager::htToolTipHeight : {				VCF::Font f = getDefaultFontFor( UIMetricsManager::ftToolTipFont );				result = f.getHeight() * 1.2222;			}			break;			case UIMetricsManager::htSeparatorHeight : {				result = 2.0;			}			break;			case UIMetricsManager::htInformationalControl : {				VCF::Font f = getDefaultFontFor( UIMetricsManager::ftControlFont );				result = f.getHeight() * 1.75;			}			break;		}		return result;	}	virtual double getPreferredSpacingFor( const UIMetricsManager::SpacingType& type )  {		double result = 0.0;		//values largely derived from the Apple HIG at		//http://developer.apple.com/techpubs/macosx/Essentials/AquaHIGuidelines/AHIGLayout/index.html		switch ( type ) {			case UIMetricsManager::stWindowBorderDelta : {				result = 20.0;			}			break;			case UIMetricsManager::stContainerBorderDelta : {				result = 8.0;			}			break;			case UIMetricsManager::stControlVerticalSpacing : {				result = 14.0;			}			break;			case UIMetricsManager::stControlHorizontalSpacing : {				result = 10.0;			}			break;			case UIMetricsManager::stInformationControlTopSpacer : {				result = 2.0;			}			break;			case UIMetricsManager::stInformationControlBottomSpacer : {				result = 8.0;			}			break;		}		return result;	}	virtual Size getDefaultSliderThumbDimensions()  {		Size result;		//where the hell do we get these ????		result.width_ = 22;		result.height_ = 22;		return result;	}	virtual Size getDefaultMenuItemDimensions( const String& caption )  {		Size result;		return result;	}	virtual Size getDefaultVerticalScrollButtonDimensions()  {		Size result;		result.width_ = 22;		result.height_ = 22;		return result;	}	virtual Size getDefaultHorizontalScrollButtonDimensions()  {		Size result;		result.width_ = 22;		result.height_ = 22;		return result;	}	virtual Size getDefaultTabDimensions( const String& caption )  {		Size result;		return result;	}};X11UIToolkit::X11UIToolkit():	defaultParentWnd_(0),	x11Display_(NULL),	consoleQuitHandlerCalled_(false),	quitEventLoopMsg_(0),	deleteWindowMsg_(0),	vcfCreateWindowMsg_(0){	X11GraphicsToolkit* toolkit = (X11GraphicsToolkit*)GraphicsToolkit::getDefaultGraphicsToolkit();	x11Display_ = toolkit->getX11Display();	//install the X11 error handler here	XSetErrorHandler( X11UIToolkit::x11ErrorHandler );	metricsMgr_ = new X11UIMetricsManager();	createDefaultParentWnd();	//install the quit handler for Ctrl+C	signal(SIGINT, X11UIToolkit::consoleQuitHandler );	//create internal atoms	deleteWindowMsg_ = XInternAtom(x11Display_, VCF_X11_DELETEWND_ATOM, False);	vcfCreateWindowMsg_ = XInternAtom(x11Display_, VCF_X11_VCFCREATEWND_ATOM, False);	quitEventLoopMsg_ = XInternAtom(x11Display_, VCF_X11_QUITEVENTLOOP_ATOM, False);	vcfPaintWindowMsg_ = XInternAtom(x11Display_, VCF_X11_PAINTWND_ATOM, False);}X11UIToolkit::~X11UIToolkit(){	timerList_.clear();	paintEventQueue_.clear();	std::deque<X11ToolkitMsg*>::iterator it = toolkitMessages_.begin();	while ( it != toolkitMessages_.end() ) {		X11ToolkitMsg* msg = *it;		delete msg;		it ++;	}	toolkitMessages_.clear();	if ( NULL != defaultParentWnd_ ) {		XDestroyWindow( x11Display_, defaultParentWnd_ );	}}ApplicationPeer* X11UIToolkit::createApplicationPeer(){	return new X11Application();}TextPeer* X11UIToolkit::createTextPeer( TextControl* component, const bool& isMultiLineControl, ComponentType componentType=CT_DEFAULT){	return new X11SimpleTextControl( component, isMultiLineControl );}TreePeer* X11UIToolkit::createTreePeer( TreeControl* component, ComponentType componentType=CT_DEFAULT){	return NULL;}ListviewPeer* X11UIToolkit::createListViewPeer( ListViewControl* component, ComponentType componentType=CT_DEFAULT){	return NULL;}DialogPeer* X11UIToolkit::createDialogPeer( Control* owner, Dialog* component, ComponentType componentType=CT_DEFAULT ){	return new X11Dialog( owner, component );}DialogPeer* X11UIToolkit::createDialogPeer(){	return new X11Dialog();}ControlPeer* X11UIToolkit::createControlPeer( Control* component, ComponentType componentType){	ControlPeer* result = NULL;	switch ( componentType ){		case CT_LIGHTWEIGHT:{			result = new LightweightComponent( component );		}		break;		case CT_DEFAULT: case CT_HEAVYWEIGHT:{			result = new X11Control( component );		}		break;	}	return result;}WindowPeer* X11UIToolkit::createWindowPeer( Control* component, Control* owner, ComponentType componentType){	return new X11Window( component, owner );}MenuItemPeer* X11UIToolkit::createMenuItemPeer( MenuItem* item ){	return NULL;}MenuBarPeer* X11UIToolkit::createMenuBarPeer( MenuBar* menuBar ){	return NULL;}PopupMenuPeer* X11UIToolkit::createPopupMenuPeer( PopupMenu* popupMenu ){	return NULL;}ButtonPeer* X11UIToolkit::createButtonPeer( CommandButton* component, ComponentType componentType){	return NULL;}HTMLBrowserPeer* X11UIToolkit::createHTMLBrowserPeer( Control* control ){	return NULL;}ContextPeer* X11UIToolkit::createContextPeer( Control* component ){	return new X11ControlContext( component->getPeer() );}CommonFileDialogPeer* X11UIToolkit::createCommonFileOpenDialogPeer( Control* owner ){	return NULL;}CommonFileDialogPeer* X11UIToolkit::createCommonFileSaveDialogPeer( Control* owner ){	return NULL;}CommonColorDialogPeer* X11UIToolkit::createCommonColorDialogPeer( Control* owner ){	return NULL;}CommonFolderBrowseDialogPeer* X11UIToolkit::createCommonFolderBrowseDialogPeer( Control* owner ){	return NULL;}CommonFontDialogPeer* X11UIToolkit::createCommonFontDialogPeer( Control* owner ){	return NULL;}DragDropPeer* X11UIToolkit::createDragDropPeer(){	return NULL;}DataObjectPeer* X11UIToolkit::createDataObjectPeer(){	return NULL;}DropTargetPeer* X11UIToolkit::createDropTargetPeer(){	return NULL;}DesktopPeer* X11UIToolkit::createDesktopPeer( Desktop* desktop ){	return new X11Desktop( desktop );}ScrollPeer* X11UIToolkit::createScrollPeer( Control* control ){	return NULL;}CursorPeer* X11UIToolkit::createCursorPeer( Cursor* cursor ){	return new X11Cursor(cursor);}ClipboardPeer* X11UIToolkit::createClipboardPeer(){	return NULL;}bool X11UIToolkit::createCaret( Control* owningControl, Image* caretImage  ){	bool result = false;	return result;}bool X11UIToolkit::destroyCaret( Control* owningControl ){	bool result = false;	return result;}void X11UIToolkit::setCaretVisible( const bool& caretVisible ){}void X11UIToolkit::setCaretPos( Point* point ){}void X11UIToolkit::postEvent( EventHandler* eventHandler, Event* event, const bool& deleteHandler ){}void X11UIToolkit::registerTimerHandler( Object* source, EventHandler* handler, const ulong32& timeoutInMilliSeconds ){}void X11UIToolkit::unregisterTimerHandler( EventHandler* handler ){}/**Notes:There are multiple places where we check hte internal status of toolkit registered timers. This isto ensure that we notify folks of timer events as close as possible to when they are actually ready.It is almost a certainty that we will NOT have 100% accuracy here, thus anything that truly needsrealtime timers should use something else. However this is no different than other window systems,for example on Win32 WM_TIMER messages are not guaranteed to be super accurate either.Also the System::sleep() call is to ensure that we don't race the CPU to 100% - without this in the loopwe get 100% CPU utilization. I beleive this is because we are use a non blocking equivalent to XPending()so we always go through the inner loop phases, as opposed to blocking on XPending(). Note thereare many way to implement this, if someone sees a better way, please suggest it!*/void X11UIToolkit::runEventLoop(){	printf( "starting X11UIToolkit runEventLoop()...\n" );	std::vector<TimerEntry> availableTimers;	Application* runningApp = Application::getRunningInstance();	//initial outer loop - this will have idle time processing if possible	bool idleTime = true;	while ( true ) {		//quit if we get a Ctrl+C from the console		if ( consoleQuitHandlerCalled_ ) {			return;		}		XFlush(x11Display_);		//check timers		timersAvailable( availableTimers );		if ( !availableTimers.empty() ) {			fireTimers( availableTimers );		}		//phase 1 of event inner loop - idle processing		while ( (!xPending() ) && (true == idleTime) ) {			if ( NULL != runningApp ) {				runningApp->idleTime();			}			//check library apps;			Enumerator<LibraryApplication*>* registeredLibs = LibraryApplication::getRegisteredLibraries();			while ( true == registeredLibs->hasMoreElements() ) {				LibraryApplication* libraryApp = registeredLibs->nextElement();				libraryApp->idleTime();			}			//only allow one cycle for now...			idleTime = false;		}		//sleep just a bit		System::sleep(1);		XEvent x11event;		Rect updateRect;		/**		phase 2 of inner event loop		this phase will capture XEvents and pass them along		to the various registered control peers.		*/		bool quitMessageReceived = false;		do {			if ( consoleQuitHandlerCalled_ ) {				return;			}			//handle toolkit messages			if ( !handleToolkitMessages() ) {				//oops looks like we got a quit message				quitMessageReceived = true;				printf( "quitMessageReceived = true, handleToolkitMessages() returned false\n" );			}			/**			Why is this here? We do a quick check to see if there are truly any events in the			queue - if there are not tehn we do NOT want to call XNextEvent, which will BLOCK			till there are events in the queue. By placing this here, we ensure that we will complete			a cycle of the loop and not cause it to hang here waiting for events			*/			if ( xPending() ) {				XNextEvent( x11Display_, &x11event );				bool doTranslateAndDispatch = true;				switch ( x11event.type ) {					case KeyPress :  {						AbstractX11Control* xwndControl = AbstractX11Control::getX11ControlFromXWindow( x11event.xkey.window );						Control* control = NULL;						if ( NULL != xwndControl ) {							control = xwndControl->getControl();							Control* currentFocusedControl = Control::getCurrentFocusedControl();							if ( NULL != currentFocusedControl ) {								if ( (control != currentFocusedControl) && (currentFocusedControl->isLightWeight()) ) {									control = currentFocusedControl;								}							}						}						X11EventMsg eventMsg( &x11event, control );						VCF::Event* event = createEventFromNativeOSEventData( (void*)&eventMsg );						if ( NULL != event ) {							//handle tabbing here							handleKeyboardEvent( reinterpret_cast<KeyboardEvent*>( event ) );							if ( event->isConsumed() ) {								doTranslateAndDispatch = false;							}						}						delete event;					}					break;					case Expose: case GraphicsExpose: {						updateRect.setRect( x11event.xexpose.x, x11event.xexpose.y,											x11event.xexpose.x + x11event.xexpose.width,											x11event.xexpose.y + x11event.xexpose.height );						//adds a new update rect to the list						AbstractX11Control* xwndControl = AbstractX11Control::getX11ControlFromXWindow( x11event.xexpose.window );						if ( NULL != xwndControl ) {							xwndControl->addUpdateRect( updateRect );							paintEventQueue_[xwndControl] = xwndControl;						}						//don't dispatch the xevent - we'll handle this as a special case						doTranslateAndDispatch = false;					}					break;					default : {						//need to figure out what a quit message is					}					break;				}				/**				if we have some to deal with lets do so here				*/				if ( doTranslateAndDispatch ) {					AbstractX11Control::handleXEvent( x11event.xany.window, &x11event );				}			}			//check timers			timersAvailable( availableTimers );			if ( !availableTimers.empty() ) {				fireTimers( availableTimers );			}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?