Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4408 lines
123 KiB

  1. //===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #define WIN32_LEAN_AND_MEAN
  8. #define OEMRESOURCE
  9. // SRC only
  10. #define PROTECTED_THINGS_DISABLE
  11. #define SUPPORT_CUSTOM_FONT_FORMAT
  12. #ifdef SUPPORT_CUSTOM_FONT_FORMAT
  13. #define _WIN32_WINNT 0x0500
  14. #endif
  15. #include <windows.h>
  16. #include <imm.h>
  17. #include <zmouse.h>
  18. #include <shellapi.h>
  19. #pragma warning( disable : 4201 )
  20. #include <mmsystem.h>
  21. #pragma warning( default : 4201 )
  22. #include <oleidl.h>
  23. #include <stdio.h>
  24. #include <basetypes.h>
  25. #include <vgui/vgui.h>
  26. #include <vgui/Dar.h>
  27. #include <vgui/IClientPanel.h>
  28. #include <vgui/ISurface.h>
  29. #include <vgui/IInputInternal.h>
  30. #include <vgui/IPanel.h>
  31. #include <vgui/ISystem.h>
  32. #include <vgui/ILocalize.h>
  33. #include <vgui/IHTML.h>
  34. #include <vgui/IVGui.h>
  35. #include <vgui/IPanel.h>
  36. #include <vgui/IScheme.h>
  37. #include <vgui/Cursor.h>
  38. #include <vgui/KeyCode.h>
  39. #include <keyvalues.h>
  40. #include <vgui/MouseCode.h>
  41. #include "vgui_internal.h"
  42. #include "bitmap.h"
  43. #include "VPanel.h"
  44. #include "utlbuffer.h"
  45. #include "utlvector.h"
  46. #include "utlsymbol.h"
  47. #include "tier1/UtlDict.h"
  48. #include "filesystem.h"
  49. #include "SteamBootStrapper.h"
  50. #include "vgui_surfacelib/Win32Font.h"
  51. #include "vgui_surfacelib/fontmanager.h"
  52. #include "vgui_key_translation.h"
  53. #include "valvefont.h"
  54. // memdbgon must be the last include file in a .cpp file!!!
  55. #include "tier0/memdbgon.h"
  56. #ifdef PlaySound
  57. #undef PlaySound
  58. #endif
  59. #ifdef CreateFont
  60. #undef CreateFont
  61. #endif
  62. using namespace vgui;
  63. #define PLAT(vpanel) (((VPanel *)vpanel)->Plat())
  64. namespace vgui
  65. {
  66. class SurfacePlat
  67. {
  68. public:
  69. HWND hwnd;
  70. HDC hdc;
  71. HDC hwndDC;
  72. HDC textureDC;
  73. HGLRC hglrc;
  74. HRGN clipRgn;
  75. HBITMAP bitmap;
  76. int bitmapSize[2];
  77. int restoreInfo[4];
  78. bool isFullscreen;
  79. bool disabled; // whether the window can take user input
  80. int fullscreenInfo[3];
  81. VPanel *embeddedPanel;
  82. bool isToolbar; // whether it has an icon in the tool tray or not
  83. HICON notifyIcon;
  84. VPANEL notifyPanel;
  85. HPanel lastKeyFocusIndex; // index to the last panel to have the focus
  86. };
  87. class Texture
  88. {
  89. public:
  90. int _id;
  91. HBITMAP _bitmap;
  92. HBITMAP _maskBitmap;
  93. bool _bMask;
  94. HICON _icon;
  95. int _wide;
  96. int _tall;
  97. void *_dib;
  98. void *_maskDib;
  99. const char *_filename;
  100. };
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose: Implementation of ISurface for use running under windows, renders using GDI
  104. // This is not used in the game, EngineSurface is used instead
  105. //-----------------------------------------------------------------------------
  106. class CWin32Surface : public CBaseAppSystem< ISurface >, public ISchemeSurface, public ILocalizeTextQuery
  107. {
  108. typedef CBaseAppSystem< ISurface > BaseClass;
  109. public:
  110. friend class CIconImage;
  111. CWin32Surface();
  112. ~CWin32Surface();
  113. virtual void Shutdown();
  114. virtual void RunFrame();
  115. virtual VPANEL GetEmbeddedPanel();
  116. virtual void SetEmbeddedPanel( VPANEL panel);
  117. // initializes the surface with the current window state
  118. virtual void SetCurrentContextPanel(VPANEL panel);
  119. virtual void PushMakeCurrent(VPANEL panel,bool useInsets);
  120. virtual void PopMakeCurrent(VPANEL panel);
  121. virtual void DrawSetColor(int r, int g, int b, int a);
  122. virtual void DrawSetColor(Color col);
  123. virtual void DrawFilledRect(int x0, int y0, int x1, int y1);
  124. virtual void DrawFilledRectFastFade( int x0, int y0, int x1, int y1, int fadeStartPt, int fadeEndPt, unsigned int alpha0, unsigned int alpha1, bool bHorizontal );
  125. virtual void DrawFilledRectFade( int x0, int y0, int x1, int y1, unsigned int alpha0, unsigned int alpha1, bool bHorizontal );
  126. virtual void DrawFilledRectArray( IntRect *pRects, int numRects );
  127. virtual void DrawOutlinedRect(int x0, int y0, int x1, int y1);
  128. virtual void DrawLine(int x0, int y0, int x1, int y1);
  129. virtual void DrawPolyLine(int *px, int *py, int numPoints);
  130. virtual void DrawSetApparentDepth( float depth ) {}
  131. virtual void DrawClearApparentDepth() {}
  132. virtual void DrawSetTextFont(HFont font);
  133. virtual void DrawSetTextColor(int r, int g, int b, int a);
  134. virtual void DrawSetTextColor(Color col);
  135. virtual void DrawSetTextPos(int x, int y);
  136. virtual void DrawSetTextScale(float sx, float sy);
  137. virtual void DrawPrintText(const wchar_t *, int textLen, FontDrawType_t drawType = FONT_DRAW_DEFAULT);
  138. virtual void DrawUnicodeChar(wchar_t wch, FontDrawType_t drawType = FONT_DRAW_DEFAULT );
  139. virtual void DrawUnicodeString( const wchar_t *pwString, FontDrawType_t drawType = FONT_DRAW_DEFAULT );
  140. virtual void DrawGetTextPos(int& x,int& y);
  141. virtual bool DrawGetTextureFile(int id, char *filename, int maxlen );
  142. virtual int DrawGetTextureId( char const *filename );
  143. virtual void DrawSetTextureFile(int id, const char *filename, int hardwareFilter, bool forceReload = false);
  144. virtual void DrawSetTexture(int id);
  145. virtual void DrawSetTextureRGBA(int id, const unsigned char *rgba, int wide, int tall );
  146. virtual void DrawSetTextureRGBAEx(int id, const unsigned char *rgba, int wide, int tall, ImageFormat imageFormat );
  147. virtual void DrawGetTextureSize(int id, int &wide, int &tall);
  148. virtual IVguiMatInfo *DrawGetTextureMatInfoFactory( int id ) { return NULL; }
  149. virtual void DrawTexturedRect(int x0, int y0, int x1, int y1);
  150. virtual int CreateNewTextureID( bool procedural );
  151. virtual bool IsTextureIDValid(int id);
  152. virtual void FreeTextureData( Texture *pTexture );
  153. virtual bool DeleteTextureByID(int id);
  154. virtual void DrawFlushText();
  155. virtual IHTML *CreateHTMLWindow(vgui::IHTMLEvents *events, VPANEL context);
  156. virtual void PaintHTMLWindow(IHTML *htmlwin);
  157. virtual void DeleteHTMLWindow(IHTML *htmlwin);
  158. virtual VPANEL GetNotifyPanel();
  159. virtual void SetNotifyIcon(VPANEL context, HTexture icon, VPANEL panelToReceiveMessages, const char *text);
  160. virtual void SetPanelForInput( VPANEL vpanel );
  161. virtual void GetScreenSize(int &wide, int &tall);
  162. virtual void SetAsTopMost(VPANEL panel, bool state);
  163. virtual void BringToFront(VPANEL panel);
  164. virtual void SetForegroundWindow(VPANEL panel);
  165. virtual void SetPanelVisible(VPANEL panel, bool visible);
  166. virtual void SetMinimized(VPANEL panel, bool state);
  167. virtual bool IsMinimized(VPANEL panel);
  168. virtual void FlashWindow(VPANEL panel, bool state);
  169. virtual void SetTitle(VPANEL panel, const wchar_t *title);
  170. virtual void SetAsToolBar(VPANEL panel, bool state);
  171. virtual bool SupportsFontFeature( FontFeature_t feature );
  172. virtual bool SupportsFeature( SurfaceFeature_t feature );
  173. virtual void SetTopLevelFocus(VPANEL panel);
  174. virtual int GetPopupCount();
  175. virtual VPANEL GetPopup(int index);
  176. virtual void AddPanel(VPANEL panel);
  177. virtual void ReleasePanel(VPANEL panel);
  178. virtual void CreatePopup(VPANEL panel, bool minimised, bool showTaskbarIcon, bool disabled, bool mouseInput, bool kbInput );
  179. virtual bool RecreateContext(VPANEL panel);
  180. virtual void EnableMouseCapture(VPANEL panel, bool state);
  181. virtual bool ShouldPaintChildPanel(VPANEL childPanel);
  182. virtual void MovePopupToFront(VPANEL panel);
  183. virtual void MovePopupToBack(VPANEL panel);
  184. virtual void SwapBuffers(VPANEL panel);
  185. virtual void Invalidate(VPANEL panel);
  186. virtual void SetCursor(HCursor cursor);
  187. virtual void ApplyChanges();
  188. virtual bool IsWithin(int x, int y);
  189. virtual bool HasFocus();
  190. virtual void GetWorkspaceBounds(int &x, int &y, int &wide, int &tall);
  191. virtual void SolveTraverse(VPANEL panel, bool forceApplySchemeSettings);
  192. virtual void PaintTraverse(VPANEL panel);
  193. virtual void RestrictPaintToSinglePanel(VPANEL panel, bool bForceAllowNonModalSurface = false);
  194. virtual void SetModalPanel(VPANEL );
  195. virtual VPANEL GetModalPanel();
  196. virtual void UnlockCursor();
  197. virtual void LockCursor();
  198. virtual void SetTranslateExtendedKeys(bool state);
  199. virtual VPANEL GetTopmostPopup();
  200. // sound
  201. virtual void PlaySound(const char *fileName);
  202. // fonts
  203. virtual HFont CreateFont();
  204. virtual bool SetFontGlyphSet(HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int nRangeMin = 0, int nRangeMax = 0);
  205. virtual int GetFontTall(HFont font);
  206. virtual int GetFontAscent(HFont font, wchar_t wch);
  207. virtual void GetCharABCwide(HFont font, int ch, int &a, int &b, int &c);
  208. virtual int GetCharacterWidth(HFont font, int ch);
  209. virtual void GetTextSize(HFont font, const wchar_t *text, int &wide, int &tall);
  210. virtual bool AddCustomFontFile(const char *fontFileName);
  211. virtual bool AddBitmapFontFile(const char *fontFileName);
  212. virtual void SetBitmapFontName( const char *pName, const char *pFontFilename );
  213. virtual const char *GetBitmapFontName( const char *pName );
  214. virtual bool SetBitmapFontGlyphSet(HFont font, const char *windowsFontName, float scalex, float scaley, int flags);
  215. virtual bool IsFontAdditive(HFont font);
  216. virtual void PrecacheFontCharacters(HFont font, wchar_t *pCharacters);
  217. virtual void ClearTemporaryFontCache( void );
  218. virtual const char *GetFontName( HFont font );
  219. virtual bool IsCursorVisible() { return true; }
  220. // gets the absolute coordinates of the screen (in screen space)
  221. void GetAbsoluteWindowBounds(int &x, int &y, int &wide, int &tall);
  222. // methods
  223. void setFocus(VPANEL panel);
  224. void GetProportionalBase( int &width, int &height ) { width = BASE_WIDTH; height = BASE_HEIGHT; }
  225. virtual void CalculateMouseVisible();
  226. virtual bool NeedKBInput();
  227. // we use the default IInput cursor functions
  228. virtual bool HasCursorPosFunctions() { return false; }
  229. virtual void SurfaceGetCursorPos(int &x, int &y) {}
  230. virtual void SurfaceSetCursorPos(int x, int y){}
  231. virtual void SetAllowHTMLJavaScript( bool state );
  232. // SRC specific interfaces
  233. virtual void DrawTexturedLine( const Vertex_t &a, const Vertex_t &b );
  234. virtual void DrawOutlinedCircle(int x, int y, int radius, int segments) ;
  235. virtual void DrawTexturedPolyLine( const Vertex_t *p,int n ) ; // (Note: this connects the first and last points).
  236. virtual void DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 );
  237. virtual void DrawTexturedPolygon(int n, Vertex_t *pVertices, bool bClipVertices = true);
  238. virtual const wchar_t *GetTitle(VPANEL panel);
  239. virtual void LockCursor( bool state );
  240. virtual bool IsCursorLocked( void ) const;
  241. virtual void SetWorkspaceInsets( int left, int top, int right, int bottom );
  242. virtual void DrawWordBubble( int x0, int y0, int x1, int y1, int nBorderThickness, Color rgbaBackground, Color rgbaBorder,
  243. bool bPointer = false, int nPointerX = 0, int nPointerY = 0, int nPointerBaseThickness = 16 );
  244. // Lower level char drawing code, call DrawGet then pass in info to DrawRender (NOT SUPPORTED BY DEFAULT SURFACE )!!!
  245. virtual bool DrawGetUnicodeCharRenderInfo( wchar_t ch, FontCharRenderInfo& info );
  246. virtual void DrawRenderCharFromInfo( const FontCharRenderInfo& info );
  247. // alpha multipliers not yet implemented
  248. virtual void DrawSetAlphaMultiplier( float alpha /* [0..1] */ ) {}
  249. virtual float DrawGetAlphaMultiplier() { return 1.0f; }
  250. // Here's where the app systems get to learn about each other
  251. virtual bool Connect( CreateInterfaceFn factory );
  252. virtual void Disconnect();
  253. // Here's where systems can access other interfaces implemented by this object
  254. // Returns NULL if it doesn't implement the requested interface
  255. virtual void *QueryInterface( const char *pInterfaceName );
  256. // Init, shutdown
  257. virtual InitReturnVal_t Init();
  258. //virtual void Shutdown();
  259. virtual const AppSystemInfo_t* GetDependencies() { return BaseClass::GetDependencies(); }
  260. virtual AppSystemTier_t GetTier() { return BaseClass::GetTier(); }
  261. virtual void Reconnect( CreateInterfaceFn factory, const char *pInterfaceName ) { BaseClass::Reconnect( factory, pInterfaceName ); }
  262. // screen size changing
  263. void OnScreenSizeChanged( int nOldWidth, int nOldHeight )
  264. {
  265. }
  266. // We don't support this for non material system surfaces (we could)
  267. virtual vgui::HCursor CreateCursorFromFile( char const *curOrAniFile, char const *pPathID )
  268. {
  269. Assert( 0 );
  270. return dc_arrow;
  271. }
  272. virtual void PaintTraverseEx(VPANEL panel, bool paintPopups = false )
  273. {
  274. PaintTraverse( panel );
  275. }
  276. virtual float GetZPos() const
  277. {
  278. return 0.0f;
  279. }
  280. virtual IImage *GetIconImageForFullPath( char const *pFullPath );
  281. virtual bool ForceScreenSizeOverride( bool bState, int wide, int tall );
  282. // LocalToScreen, ParentLocalToScreen fixups for explicit PaintTraverse calls on Panels not at 0, 0 position
  283. virtual bool ForceScreenPosOffset( bool bState, int x, int y );
  284. virtual void OffsetAbsPos( int &x, int &y );
  285. virtual void SetAbsPosForContext( int id, int x, int y );
  286. virtual void GetAbsPosForContext( int id, int &x, int& y );
  287. // split screen state changed, etc.
  288. void ResetFontCaches()
  289. {
  290. }
  291. virtual bool IsScreenSizeOverrideActive( void );
  292. virtual bool IsScreenPosOverrideActive( void );
  293. virtual int GetTextureNumFrames( int id );
  294. virtual void DrawSetTextureFrame( int id, int nFrame, unsigned int *pFrameCache );
  295. virtual void GetClipRect( int &x0, int &y0, int &x1, int &y1 );
  296. virtual void SetClipRect( int x0, int y0, int x1, int y1 );
  297. virtual void SetLanguage( const char *pLanguage );
  298. virtual const char *GetLanguage();
  299. virtual void DrawTexturedRectEx( DrawTexturedRectParms_t *pDrawParms );
  300. // Methods of ILocalizeTextQuery
  301. public:
  302. virtual int ComputeTextWidth( const wchar_t *pString );
  303. void GetKernedCharWidth( HFont font, wchar_t ch, wchar_t chBefore, wchar_t chAfter, float &wide, float &flabcA, float &flabcC )
  304. {
  305. Assert( 0 );
  306. wide = 0.0f;
  307. flabcA = 0.0f;
  308. flabcC = 0.0f;
  309. }
  310. virtual void DestroyTextureID( int id );
  311. virtual void DrawUpdateRegionTextureRGBA( int nTextureID, int x, int y, const unsigned char *pchData, int wide, int tall, ImageFormat imageFormat )
  312. {
  313. }
  314. virtual bool BHTMLWindowNeedsPaint(IHTML *htmlwin)
  315. {
  316. return false;
  317. }
  318. virtual const char *GetWebkitHTMLUserAgentString();
  319. virtual void *Deprecated_AccessChromeHTMLController() OVERRIDE { return NULL; }
  320. virtual void DrawSetTextureRGBALinear(int id, const unsigned char *rgba, int wide, int tall );
  321. private:
  322. CUtlDict< IImage *, unsigned short > m_FileTypeImages;
  323. enum { BASE_HEIGHT = 480, BASE_WIDTH = 640 };
  324. bool LoadTGA(Texture *texture, const char *filename);
  325. bool LoadBMP(Texture *texture, const char *filename);
  326. void InternalThinkTraverse(VPANEL panel);
  327. void InternalSolveTraverse(VPANEL panel);
  328. void InternalSchemeSettingsTraverse(VPANEL panel, bool forceApplySchemeSettings);
  329. VPANEL GetContextPanelForChildPanel(VPANEL childPanel);
  330. void initStaticData();
  331. // sets the current line drawing color, called by DrawSetTextColor
  332. void SetLineColor(Color col);
  333. VPANEL _embeddedPanel; // main panel
  334. VPANEL _notifyPanel;
  335. VPANEL _currentContextPanel;
  336. HTexture _notifyIcon;
  337. Dar<VPANEL> _popupList; // list of panels that have their own win32 window
  338. HICON _currentCursor;
  339. OSVERSIONINFO m_WindowsVersion;
  340. bool m_bSupportsUnicode;
  341. CUtlVector<CUtlSymbol> m_CustomFontFileNames;
  342. bool LoadChromeHTML();
  343. // current font info
  344. HFont m_hCurrentFont;
  345. CWin32Font *m_pActiveFont;
  346. HPEN pen; // the pen used to draw lines
  347. bool _needKB;
  348. bool _needMouse;
  349. int m_TextPos[2];
  350. Texture *m_pCurrentTexture;
  351. static bool TextureLessFunc(const Texture &lhs, const Texture &rhs);
  352. Texture *GetTextureById(int id);
  353. Texture *AllocTextureForId(int id);
  354. int GetNumTextures();
  355. CUtlRBTree<Texture, int> m_VGuiSurfaceTextures;
  356. bool m_bAllowJavaScript;
  357. struct ScreenOverride_t
  358. {
  359. ScreenOverride_t() : m_bActive( false )
  360. {
  361. m_nValue[ 0 ] = m_nValue[ 1 ] = 0;
  362. }
  363. bool m_bActive;
  364. int m_nValue[ 2 ];
  365. };
  366. ScreenOverride_t m_ScreenSizeOverride;
  367. ScreenOverride_t m_ScreenPosOverride;
  368. struct ContextAbsPos_t
  369. {
  370. ContextAbsPos_t() : id( -1 )
  371. {
  372. m_nPos[ 0 ] = m_nPos[ 1 ] = 0;
  373. }
  374. static bool Less( const ContextAbsPos_t &lhs, const ContextAbsPos_t &rhs )
  375. {
  376. return lhs.id < rhs.id;
  377. }
  378. int id;
  379. int m_nPos[ 2 ];
  380. };
  381. CUtlRBTree< ContextAbsPos_t > m_ContextAbsPos;
  382. };
  383. CWin32Surface g_Surface;
  384. EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CWin32Surface, ISurface, VGUI_SURFACE_INTERFACE_VERSION, g_Surface );
  385. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CWin32Surface, ISchemeSurface, SCHEME_SURFACE_INTERFACE_VERSION, g_Surface );
  386. //!! these defines duplicated in Surface_Win32.cpp
  387. #define WM_MY_TRAY_NOTIFICATION (WM_USER+1)
  388. static UINT staticShutdownMsg = 0;
  389. static HICON staticDefaultCursor[20];
  390. static WNDCLASS staticWndclass = { NULL };
  391. static ATOM staticWndclassAtom = 0;
  392. static bool staticStaticDataInitialized = false;
  393. static bool staticSurfaceAvailable;
  394. // these functions defined below
  395. static LRESULT CALLBACK staticProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam);
  396. static void staticNotifyIconProc(HWND hwnd, WPARAM wparam, LPARAM lparam);
  397. #ifdef DEBUG_TIMING
  398. #define START_TIMER() \
  399. float paintTime;\
  400. static LARGE_INTEGER ticksPerSecond = { 0 };\
  401. if (!ticksPerSecond.QuadPart)\
  402. {\
  403. QueryPerformanceFrequency(&ticksPerSecond);\
  404. }\
  405. LARGE_INTEGER Start, end;\
  406. QueryPerformanceCounter(&Start);
  407. #define END_TIMER(x) \
  408. QueryPerformanceCounter(&end);\
  409. paintTime = (float)(((end.QuadPart - Start.QuadPart) * 1000000) / ticksPerSecond.QuadPart) / 1000;\
  410. if (paintTime > 1.0f) Msg(x, paintTime);
  411. #else
  412. #define START_TIMER()
  413. #define END_TIMER(x)
  414. #endif // DEBUG_TIMING
  415. //-----------------------------------------------------------------------------
  416. // Purpose: Handles drag and drop
  417. //-----------------------------------------------------------------------------
  418. class CSurfaceDragDropTarget : public IDropTarget
  419. {
  420. public:
  421. CSurfaceDragDropTarget()
  422. {
  423. _refCount = 0;
  424. _dragData = NULL;
  425. OleInitialize(NULL);
  426. }
  427. private:
  428. unsigned int _refCount;
  429. KeyValues *_dragData;
  430. virtual HRESULT STDMETHODCALLTYPE QueryInterface(
  431. /* [in] */ REFIID riid,
  432. /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
  433. {
  434. if (riid == IID_IDropTarget)
  435. {
  436. *ppvObject = (IDropTarget *)this;
  437. return S_OK;
  438. }
  439. return E_NOINTERFACE;
  440. }
  441. virtual ULONG STDMETHODCALLTYPE AddRef( void)
  442. {
  443. return ++_refCount;
  444. }
  445. virtual ULONG STDMETHODCALLTYPE Release( void)
  446. {
  447. return --_refCount;
  448. }
  449. virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  450. {
  451. if (_dragData)
  452. {
  453. _dragData->deleteThis();
  454. }
  455. _dragData = calculateData(pDataObject);
  456. return DragOver(grfKeyState, pt, pdwEffect);
  457. }
  458. virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  459. {
  460. *pdwEffect = DROPEFFECT_NONE;
  461. if (!_dragData || !g_pIVgui->IsRunning())
  462. return S_OK;
  463. // get the panel the mouse is over
  464. VPANEL mouseOver = g_pInput->GetMouseOver();
  465. if (mouseOver)
  466. {
  467. // check to see if the panel will accept this message
  468. if (((VPanel *)mouseOver)->Client()->RequestInfo(_dragData))
  469. {
  470. *pdwEffect = DROPEFFECT_COPY;
  471. }
  472. }
  473. return S_OK;
  474. }
  475. virtual HRESULT STDMETHODCALLTYPE DragLeave()
  476. {
  477. return S_OK;
  478. }
  479. virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
  480. {
  481. *pdwEffect = DROPEFFECT_NONE;
  482. if (!_dragData || !g_pIVgui->IsRunning())
  483. return S_OK;
  484. // get the panel the mouse is over
  485. VPANEL target = (VPANEL)_dragData->GetPtr("AcceptPanel");
  486. if (target && _dragData)
  487. {
  488. // check to see if the panel will accept this message
  489. g_pIVgui->PostMessage(target, _dragData, NULL);
  490. _dragData = NULL;
  491. }
  492. if (_dragData)
  493. {
  494. _dragData->deleteThis();
  495. }
  496. _dragData = NULL;
  497. return S_OK;
  498. }
  499. // internal methods
  500. virtual KeyValues *calculateData(IDataObject *pDataObject)
  501. {
  502. KeyValues *dragData = NULL;
  503. // check on the type of data
  504. FORMATETC format =
  505. {
  506. CF_TEXT,
  507. NULL,
  508. DVASPECT_CONTENT,
  509. -1,
  510. TYMED_HGLOBAL
  511. };
  512. STGMEDIUM storage;
  513. if (pDataObject->GetData(&format, &storage) == S_OK)
  514. {
  515. // we got some data
  516. if (storage.tymed == TYMED_HGLOBAL)
  517. {
  518. const char *buf = (const char *)GlobalLock(storage.hGlobal);
  519. dragData = new KeyValues("DragDrop", "type", "text", "text", buf);
  520. GlobalUnlock(storage.hGlobal);
  521. }
  522. ReleaseStgMedium(&storage);
  523. }
  524. else
  525. {
  526. // try getting a file
  527. format.cfFormat = CF_HDROP;
  528. if (pDataObject->GetData(&format, &storage) == S_OK && storage.tymed == TYMED_HGLOBAL)
  529. {
  530. dragData = new KeyValues("DragDrop", "type", "files");
  531. KeyValues *fileList = dragData->FindKey("list", true);
  532. // parse out the file list
  533. HDROP hdrop = (HDROP)GlobalLock(storage.hGlobal);
  534. char namebuf[32], buf[512];
  535. int count = DragQueryFile(hdrop, 0xFFFFFFFF, buf, 511);
  536. for (int i = 0; i < count; i++)
  537. {
  538. Q_snprintf(namebuf, sizeof( namebuf ), "%d", i);
  539. DragQueryFile(hdrop, i, buf, 511);
  540. fileList->SetString(namebuf, buf);
  541. }
  542. GlobalUnlock(storage.hGlobal);
  543. }
  544. }
  545. return dragData;
  546. }
  547. };
  548. static CSurfaceDragDropTarget staticDragDropTarget;
  549. bool CWin32Surface::TextureLessFunc(const Texture &lhs, const Texture &rhs)
  550. {
  551. return lhs._id < rhs._id;
  552. }
  553. Texture *CWin32Surface::GetTextureById(int id)
  554. {
  555. Texture findTex = { id };
  556. int index = m_VGuiSurfaceTextures.Find(findTex);
  557. if (m_VGuiSurfaceTextures.IsValidIndex(index))
  558. {
  559. return &m_VGuiSurfaceTextures[index];
  560. }
  561. return NULL;
  562. }
  563. Texture *CWin32Surface::AllocTextureForId(int id)
  564. {
  565. Texture newTex = { id };
  566. int index = m_VGuiSurfaceTextures.Insert(newTex);
  567. return &m_VGuiSurfaceTextures[index];
  568. }
  569. int CWin32Surface::GetNumTextures()
  570. {
  571. return m_VGuiSurfaceTextures.Count();
  572. }
  573. //-----------------------------------------------------------------------------
  574. // Purpose:
  575. //-----------------------------------------------------------------------------
  576. static void staticGenerateIconForTexture(Texture *texture, HDC hdc)
  577. {
  578. // see if there is an iconic version of the texture file first
  579. char buf[256];
  580. Q_snprintf(buf, sizeof( buf ), "%s.ico", texture->_filename);
  581. texture->_icon = (HICON)::LoadImage(NULL, buf, IMAGE_ICON, 16, 16, LR_LOADFROMFILE | LR_DEFAULTSIZE);
  582. if (texture->_icon)
  583. return;
  584. if (texture->_wide > 32 || texture->_tall > 32)
  585. return;
  586. // generate an icon from the tga
  587. // generate the AND plane based on the alpha
  588. uchar planeAND[32 * 32 / 8];
  589. /* !! disabled until verified
  590. //
  591. // from the alpha of the bitmap, generate a bitmask
  592. //
  593. uchar *ptr = (uchar *)texture->_dib + 3; // jump to alpha portion
  594. uchar *ptrEnd = (uchar *)texture->_dib + (texture->_wide * texture->_tall * 4);
  595. uchar *andPtr = planeAND;
  596. while (ptr < ptrEnd)
  597. {
  598. // Start all empty
  599. *andPtr = 0;
  600. // assume the number of pixel is a multiple of 8
  601. // if the alpha is high enough, then mask out the pixel
  602. // it's two bits per pixel, strangely enough
  603. if (*ptr > 127) { *andPtr |= 0x03; } ptr += 4;
  604. if (*ptr > 127) { *andPtr |= 0x0C; } ptr += 4;
  605. if (*ptr > 127) { *andPtr |= 0x30; } ptr += 4;
  606. if (*ptr > 127) { *andPtr |= 0xC0; } ptr += 4;
  607. andPtr++;
  608. }
  609. */
  610. memset(planeAND, 0x00, sizeof(planeAND));
  611. HBITMAP mask = ::CreateBitmap(texture->_wide, texture->_tall, 1, 1, planeAND);
  612. // create the icon
  613. ICONINFO iconInfo;
  614. iconInfo.fIcon = TRUE;
  615. iconInfo.xHotspot = 8;
  616. iconInfo.yHotspot = 8;
  617. iconInfo.hbmMask = mask;
  618. iconInfo.hbmColor = texture->_bitmap;
  619. texture->_icon = ::CreateIconIndirect(&iconInfo);
  620. ::DeleteObject(mask);
  621. }
  622. //-----------------------------------------------------------------------------
  623. // Purpose: Constructor, basic variable initialization
  624. //-----------------------------------------------------------------------------
  625. CWin32Surface::CWin32Surface() : m_VGuiSurfaceTextures(0, 128, TextureLessFunc), m_ContextAbsPos( 0, 0, ContextAbsPos_t::Less )
  626. {
  627. _currentCursor = NULL;
  628. m_pCurrentTexture = NULL;
  629. initStaticData();
  630. staticSurfaceAvailable = false;
  631. m_bAllowJavaScript = false;
  632. m_hCurrentFont = 0;
  633. pen = NULL;
  634. _needKB = true;
  635. _needMouse = true;
  636. HRESULT hr;
  637. // this step is IMPORTANT , it turns "on" COM
  638. if (FAILED(hr = CoInitialize(NULL)))
  639. {
  640. // failed
  641. }
  642. // get our version info
  643. m_WindowsVersion.dwOSVersionInfoSize = sizeof(m_WindowsVersion);
  644. GetVersionEx(&m_WindowsVersion);
  645. if (m_WindowsVersion.dwMajorVersion >= 5)
  646. {
  647. m_bSupportsUnicode = true;
  648. }
  649. else
  650. {
  651. m_bSupportsUnicode = false;
  652. }
  653. m_TextPos[0] = m_TextPos[1] = 0;
  654. }
  655. //-----------------------------------------------------------------------------
  656. // Purpose: Destructor
  657. //-----------------------------------------------------------------------------
  658. CWin32Surface::~CWin32Surface()
  659. {
  660. // ensure we don't try and process any more windows messages
  661. staticSurfaceAvailable = false;
  662. // free all the textures
  663. for (int i = 0; i < m_VGuiSurfaceTextures.MaxElement(); i++)
  664. {
  665. if (!m_VGuiSurfaceTextures.IsValidIndex(i))
  666. continue;
  667. Texture *texture = &m_VGuiSurfaceTextures[i];
  668. if (texture->_bitmap)
  669. {
  670. ::DeleteObject(texture->_bitmap);
  671. }
  672. if (texture->_maskBitmap)
  673. {
  674. ::DeleteObject(texture->_maskBitmap);
  675. }
  676. if (texture->_icon)
  677. {
  678. ::DestroyIcon(texture->_icon);
  679. }
  680. }
  681. CoUninitialize(); // turn com off
  682. }
  683. //-----------------------------------------------------------------------------
  684. // Purpose: Shuts down app
  685. //-----------------------------------------------------------------------------
  686. void CWin32Surface::Shutdown()
  687. {
  688. for ( int i = m_FileTypeImages.First(); i != m_FileTypeImages.InvalidIndex(); i = m_FileTypeImages.Next( i ) )
  689. {
  690. delete m_FileTypeImages[ i ];
  691. }
  692. m_FileTypeImages.RemoveAll();
  693. // free the fonts
  694. FontManager().ClearAllFonts();
  695. // release any custom font files
  696. {for (int i = 0; i < m_CustomFontFileNames.Count(); i++)
  697. {
  698. ::RemoveFontResource(m_CustomFontFileNames[i].String());
  699. }}
  700. m_CustomFontFileNames.RemoveAll();
  701. // ensure we don't try and process windows messages during Shutdown
  702. staticSurfaceAvailable = false;
  703. // release any panels still with surfaces
  704. while (GetPopupCount())
  705. {
  706. ReleasePanel(GetPopup(0));
  707. }
  708. // kill our windows instance
  709. ::UnregisterClass("Surface", ::GetModuleHandle(NULL));
  710. staticWndclassAtom = NULL;
  711. }
  712. //-----------------------------------------------------------------------------
  713. // Purpose:
  714. //-----------------------------------------------------------------------------
  715. VPANEL CWin32Surface::GetEmbeddedPanel()
  716. {
  717. return _embeddedPanel;
  718. }
  719. // SRC specific interfaces
  720. void CWin32Surface::DrawTexturedLine( const Vertex_t &a, const Vertex_t &b )
  721. {
  722. }
  723. void CWin32Surface::DrawOutlinedCircle(int x, int y, int radius, int segments)
  724. {
  725. }
  726. void CWin32Surface::DrawTexturedPolyLine( const Vertex_t *p,int n )
  727. {
  728. }
  729. void CWin32Surface::DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 )
  730. {
  731. }
  732. void CWin32Surface::DrawTexturedPolygon(int n, Vertex_t *pVertices, bool bClipVertices /*= true*/)
  733. {
  734. NOTE_UNUSED( bClipVertices );
  735. POINT *pt;
  736. HDC hdc = PLAT(_currentContextPanel)->hdc;
  737. pt = (POINT *)malloc(sizeof(POINT) * n);
  738. if(pt)
  739. {
  740. for(int i=0;i<n;i++)
  741. {
  742. pt[i].x= pVertices[i].m_Position.x;
  743. pt[i].y= pVertices[i].m_Position.y;
  744. }
  745. COLORREF pencolor = ::GetTextColor(hdc);
  746. COLORREF brushcolor = ::GetBkColor(hdc);
  747. //Set the pen color to the current brush color to avoid strange outlines on our polygons
  748. DrawSetTextColor(GetRValue(brushcolor),GetGValue(brushcolor),GetBValue(brushcolor),255);
  749. //create a brush
  750. HBRUSH hbrush = ::CreateSolidBrush(brushcolor);
  751. HBRUSH oldBrush = (HBRUSH)::SelectObject(hdc, hbrush);
  752. ::Polygon(hdc, pt, n);
  753. ::SelectObject(hdc, oldBrush);
  754. ::DeleteObject(hbrush);
  755. free(pt);
  756. //restore pen colour
  757. DrawSetTextColor(GetRValue(pencolor),GetGValue(pencolor),GetBValue(pencolor),255);
  758. }
  759. }
  760. const wchar_t *CWin32Surface::GetTitle(VPANEL panel)
  761. {
  762. return L"";
  763. }
  764. void CWin32Surface::LockCursor( bool state )
  765. {
  766. }
  767. bool CWin32Surface::IsCursorLocked( void ) const
  768. {
  769. return false;
  770. }
  771. void CWin32Surface::SetWorkspaceInsets( int left, int top, int right, int bottom )
  772. {
  773. }
  774. void CWin32Surface::DrawWordBubble( int x0, int y0, int x1, int y1, int nBorderThickness, Color rgbaBackground, Color rgbaBorder, bool bPointer, int nPointerX, int nPointerY, int nPointerBaseThickness )
  775. {
  776. int nOldClipX0, nOldClipY0, nOldClipX1, nOldClipY1;
  777. GetClipRect( nOldClipX0, nOldClipY0, nOldClipX1, nOldClipY1 );
  778. SetClipRect( INT16_MIN, INT16_MIN, INT16_MAX, INT16_MAX );
  779. int nBackgroundWide = x1 - x0;
  780. int nBackgroundTall = y1 - y0;
  781. DrawSetColor( rgbaBackground );
  782. DrawFilledRect( x0, y0, x1, y1 );
  783. DrawSetTexture( -1 );
  784. Vector2D vecZero = Vector2D( 0.0f, 0.0f );
  785. // Figure out the relative position of the thing we're pointing at
  786. if ( nPointerY >= y0 && nPointerY < y0 + nBackgroundTall )
  787. {
  788. // Pointer is pointing inside the bubble!
  789. bPointer = false;
  790. }
  791. int nHalfPointerBaseTopWide, nHalfPointerBaseBottomWide;
  792. if ( bPointer )
  793. {
  794. if ( nPointerY < y0 )
  795. {
  796. // Pointing at something above bubble!
  797. nHalfPointerBaseTopWide = nPointerBaseThickness / 2;
  798. nHalfPointerBaseBottomWide = nPointerBaseThickness;
  799. // Draw the up pointer from polygons
  800. vgui::Vertex_t pointerVerts[ 3 ] =
  801. {
  802. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseTopWide, y0 ), vecZero ),
  803. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  804. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 ), vecZero )
  805. };
  806. DrawTexturedPolygon( 3, pointerVerts );
  807. }
  808. else
  809. {
  810. // Pointing at something below bubble!
  811. nHalfPointerBaseTopWide = nPointerBaseThickness;
  812. nHalfPointerBaseBottomWide = nPointerBaseThickness / 2;
  813. // Draw the down pointer from polygons
  814. vgui::Vertex_t pointerVerts[ 3 ] =
  815. {
  816. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 + nBackgroundTall ), vecZero ),
  817. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  818. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseBottomWide, y0 + nBackgroundTall ), vecZero )
  819. };
  820. DrawTexturedPolygon( 3, pointerVerts );
  821. }
  822. }
  823. else
  824. {
  825. // No pointer so the top and bottom separations are both closed
  826. nHalfPointerBaseTopWide = nPointerBaseThickness;
  827. nHalfPointerBaseBottomWide = nPointerBaseThickness;
  828. }
  829. // Build a border out of polygons!
  830. DrawSetColor( rgbaBorder );
  831. DrawFilledRect( x0, y0 - nBorderThickness, x0 + nHalfPointerBaseTopWide, y0 );
  832. DrawFilledRect( x0 + nPointerBaseThickness, y0 - nBorderThickness, x0 + nBackgroundWide, y0 );
  833. DrawFilledRect( x0 - nBorderThickness, y0, x0, y0 + nBackgroundTall );
  834. DrawFilledRect( x0 + nBackgroundWide, y0, x0 + nBackgroundWide + nBorderThickness, y0 + nBackgroundTall );
  835. DrawFilledRect( x0, y0 + nBackgroundTall, x0 + nHalfPointerBaseBottomWide, y0 + nBackgroundTall + nBorderThickness );
  836. DrawFilledRect( x0 + nPointerBaseThickness, y0 + nBackgroundTall, x0 + nBackgroundWide, y0 + nBackgroundTall + nBorderThickness );
  837. const int nNumCornerTris = 4;
  838. vgui::Vertex_t cornerVerts[ nNumCornerTris * 3 ] =
  839. {
  840. // Corner TL
  841. vgui::Vertex_t( Vector2D( x0, y0 - nBorderThickness ), vecZero ),
  842. vgui::Vertex_t( Vector2D( x0, y0 ), vecZero ),
  843. vgui::Vertex_t( Vector2D( x0 - nBorderThickness, y0 ), vecZero ),
  844. // Corner TR
  845. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide, y0 - nBorderThickness ), vecZero ),
  846. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide + nBorderThickness, y0 ), vecZero ),
  847. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide, y0 ), vecZero ),
  848. // Corner BL
  849. vgui::Vertex_t( Vector2D( x0 - nBorderThickness, y0 + nBackgroundTall ), vecZero ),
  850. vgui::Vertex_t( Vector2D( x0, y0 + nBackgroundTall ), vecZero ),
  851. vgui::Vertex_t( Vector2D( x0, y0 + nBackgroundTall + nBorderThickness ), vecZero ),
  852. // Corner BR
  853. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide, y0 + nBackgroundTall ), vecZero ),
  854. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide + nBorderThickness, y0 + nBackgroundTall ), vecZero ),
  855. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide, y0 + nBackgroundTall + nBorderThickness ), vecZero )
  856. };
  857. for ( int nTri = 0; nTri < nNumCornerTris; ++nTri )
  858. {
  859. DrawTexturedPolygon( 3, cornerVerts + nTri * 3 );
  860. }
  861. if ( bPointer )
  862. {
  863. if ( nPointerY < y0 )
  864. {
  865. // Draw the up pointer border from polygons
  866. const int nNumPointerQuads = 3;
  867. vgui::Vertex_t pointerVerts[ nNumPointerQuads * 4 ] =
  868. {
  869. // Pointer left
  870. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseTopWide, y0 ), vecZero ),
  871. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseTopWide, y0 - nBorderThickness ), vecZero ),
  872. vgui::Vertex_t( Vector2D( nPointerX - nBorderThickness, nPointerY - nBorderThickness ), vecZero ),
  873. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  874. // Pointer right
  875. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 - nBorderThickness ), vecZero ),
  876. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 ), vecZero ),
  877. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  878. vgui::Vertex_t( Vector2D( nPointerX + nBorderThickness, nPointerY - nBorderThickness ), vecZero ),
  879. // Pointer bottom
  880. vgui::Vertex_t( Vector2D( nPointerX, nPointerY - nBorderThickness * 2 ), vecZero ),
  881. vgui::Vertex_t( Vector2D( nPointerX + nBorderThickness, nPointerY - nBorderThickness ), vecZero ),
  882. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  883. vgui::Vertex_t( Vector2D( nPointerX - nBorderThickness, nPointerY - nBorderThickness ), vecZero )
  884. };
  885. for ( int nQuad = 0; nQuad < nNumPointerQuads; ++nQuad )
  886. {
  887. DrawTexturedPolygon( 4, pointerVerts + nQuad * 4 );
  888. }
  889. }
  890. else
  891. {
  892. // Draw the down pointer from polygons
  893. const int nNumPointerQuads = 3;
  894. vgui::Vertex_t pointerVerts[ nNumPointerQuads * 4 ] =
  895. {
  896. // Pointer left
  897. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseBottomWide, y0 + nBackgroundTall + nBorderThickness ), vecZero ),
  898. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseBottomWide, y0 + nBackgroundTall ), vecZero ),
  899. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  900. vgui::Vertex_t( Vector2D( nPointerX - nBorderThickness, nPointerY + nBorderThickness ), vecZero ),
  901. // Pointer right
  902. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 + nBackgroundTall + nBorderThickness ), vecZero ),
  903. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 + nBackgroundTall ), vecZero ),
  904. vgui::Vertex_t( Vector2D( nPointerX + nBorderThickness, nPointerY + nBorderThickness ), vecZero ),
  905. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  906. // Pointer bottom
  907. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  908. vgui::Vertex_t( Vector2D( nPointerX + nBorderThickness, nPointerY + nBorderThickness ), vecZero ),
  909. vgui::Vertex_t( Vector2D( nPointerX, nPointerY + nBorderThickness * 2 ), vecZero ),
  910. vgui::Vertex_t( Vector2D( nPointerX - nBorderThickness, nPointerY + nBorderThickness ), vecZero )
  911. };
  912. for ( int nQuad = 0; nQuad < nNumPointerQuads; ++nQuad )
  913. {
  914. DrawTexturedPolygon( 4, pointerVerts + nQuad * 4 );
  915. }
  916. }
  917. }
  918. SetClipRect( nOldClipX0, nOldClipY0, nOldClipX1, nOldClipY1 );
  919. }
  920. //-----------------------------------------------------------------------------
  921. // Connect, disconnect...
  922. //-----------------------------------------------------------------------------
  923. bool CWin32Surface::Connect( CreateInterfaceFn factory )
  924. {
  925. return true;
  926. }
  927. void CWin32Surface::Disconnect()
  928. {
  929. }
  930. //-----------------------------------------------------------------------------
  931. // Access to other interfaces...
  932. //-----------------------------------------------------------------------------
  933. void *CWin32Surface::QueryInterface( const char *pInterfaceName )
  934. {
  935. if (!Q_strncmp( pInterfaceName, VGUI_SURFACE_INTERFACE_VERSION, Q_strlen(VGUI_SURFACE_INTERFACE_VERSION) + 1))
  936. return (vgui::ISurface*)this;
  937. if (!Q_strncmp( pInterfaceName, SCHEME_SURFACE_INTERFACE_VERSION, Q_strlen(SCHEME_SURFACE_INTERFACE_VERSION) + 1))
  938. return (ISchemeSurface*)this;
  939. return NULL;
  940. }
  941. //-----------------------------------------------------------------------------
  942. // Initialization and shutdown...
  943. //-----------------------------------------------------------------------------
  944. InitReturnVal_t CWin32Surface::Init( void )
  945. {
  946. return INIT_FAILED;
  947. }
  948. //-----------------------------------------------------------------------------
  949. // Purpose: Sets up the panel for use
  950. // Input : *embeddedPanel - Main panel that becomes the top of the hierarchy
  951. //-----------------------------------------------------------------------------
  952. void CWin32Surface::SetEmbeddedPanel( VPANEL panel )
  953. {
  954. _embeddedPanel = panel;
  955. staticSurfaceAvailable = true;
  956. SetCurrentContextPanel(panel);
  957. CreatePopup(panel, false, true, false, true, true);
  958. // send a message to ourselves every 50ms (20Hz) so that we don't block in the message queue too long
  959. ::SetTimer(PLAT(_currentContextPanel)->hwnd, 0, 50, (TIMERPROC) NULL);
  960. // fonts initialization
  961. char language[64];
  962. if (g_pSystem->GetRegistryString("HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Language", language, sizeof(language)-1))
  963. {
  964. FontManager().SetLanguage(language);
  965. }
  966. else
  967. {
  968. FontManager().SetLanguage("english");
  969. }
  970. }
  971. // Lower level char drawing code, call DrawGet then pass in info to DrawRender
  972. bool CWin32Surface::DrawGetUnicodeCharRenderInfo( wchar_t ch, FontCharRenderInfo& info )
  973. {
  974. // Only supported in engine renderer!
  975. Assert( 0 );
  976. info.valid = false;
  977. return false;
  978. }
  979. void CWin32Surface::DrawRenderCharFromInfo( const FontCharRenderInfo& info )
  980. {
  981. Assert( 0 );
  982. }
  983. //-----------------------------------------------------------------------------
  984. // Purpose: Sets the current drawing context
  985. //-----------------------------------------------------------------------------
  986. void CWin32Surface::SetCurrentContextPanel(VPANEL panel)
  987. {
  988. _currentContextPanel = panel;
  989. }
  990. //-----------------------------------------------------------------------------
  991. // Purpose:
  992. //-----------------------------------------------------------------------------
  993. VPANEL CWin32Surface::GetContextPanelForChildPanel(VPANEL childPanel)
  994. {
  995. VPANEL contextPanel = childPanel;
  996. while (contextPanel && !PLAT(contextPanel))
  997. {
  998. contextPanel = (VPANEL)((VPanel *)contextPanel)->GetParent();
  999. }
  1000. return contextPanel;
  1001. }
  1002. // static currently used win32 Paint info
  1003. static ::PAINTSTRUCT s_CurrentPaintStruct;
  1004. void CWin32Surface::PushMakeCurrent(VPANEL panel, bool useInsets)
  1005. {
  1006. // find the win32 window context from the hierarchy
  1007. VPANEL currentContextPanel = GetContextPanelForChildPanel(panel);
  1008. SetCurrentContextPanel(currentContextPanel);
  1009. // clear the current active font so that it will be reset
  1010. m_pActiveFont = NULL;
  1011. if (!currentContextPanel)
  1012. {
  1013. // no drawing context found, something is seriously wrong
  1014. Msg( "Warning: VPanel with no drawing context\n" );
  1015. }
  1016. int inset[4];
  1017. //!! need to make the inset part of VPanel
  1018. ((VPanel *)panel)->Client()->GetInset(inset[0],inset[1],inset[2],inset[3]);
  1019. if(!useInsets)
  1020. {
  1021. inset[0]=0;
  1022. inset[1]=0;
  1023. inset[2]=0;
  1024. inset[3]=0;
  1025. }
  1026. int absThis[4];
  1027. ((VPanel *)_currentContextPanel)->GetAbsPos(absThis[0], absThis[1]);
  1028. ((VPanel *)_currentContextPanel)->GetSize(absThis[2], absThis[3]);
  1029. absThis[2] += absThis[0];
  1030. absThis[3] += absThis[1];
  1031. int absPanel[4];
  1032. ((VPanel *)panel)->GetAbsPos(absPanel[0], absPanel[1]);
  1033. ((VPanel *)panel)->GetSize(absPanel[2], absPanel[3]);
  1034. absPanel[2] += absPanel[0];
  1035. absPanel[3] += absPanel[1];
  1036. int clipRect[4];
  1037. ((VPanel *)panel)->Client()->GetClipRect(clipRect[0],clipRect[1],clipRect[2],clipRect[3]);
  1038. if ( _currentContextPanel == panel )
  1039. {
  1040. // this panel has it's own window, so use screen space
  1041. ::SetViewportOrgEx(PLAT(_currentContextPanel)->hdc,0+inset[0],0+inset[1],0);
  1042. }
  1043. else
  1044. {
  1045. // child window, so set win32 up so all subsequent drawing calls are done in local space
  1046. ::SetViewportOrgEx(PLAT(_currentContextPanel)->hdc,(absPanel[0]+inset[0])-absThis[0],(absPanel[1]+inset[1])-absThis[1],0);
  1047. }
  1048. // setup clipping
  1049. // get and translate clipRect into surface space, then factor in inset
  1050. int x0 = clipRect[0] - absThis[0];
  1051. int y0 = clipRect[1] - absThis[1];
  1052. int x1 = (clipRect[2] - absThis[0]) - inset[2];
  1053. int y1 = (clipRect[3] - absThis[1]) - inset[3];
  1054. //set the rect and select to make it current
  1055. ::SetRectRgn(PLAT(_currentContextPanel)->clipRgn,x0,y0,x1,y1);
  1056. ::SelectObject(PLAT(_currentContextPanel)->hdc, PLAT(_currentContextPanel)->clipRgn);
  1057. }
  1058. //-----------------------------------------------------------------------------
  1059. // Purpose:
  1060. //-----------------------------------------------------------------------------
  1061. void CWin32Surface::PopMakeCurrent(VPANEL panel)
  1062. {
  1063. if (panel == _currentContextPanel)
  1064. {
  1065. // reset the current panel to be the main panel
  1066. SetCurrentContextPanel(_embeddedPanel);
  1067. }
  1068. }
  1069. //-----------------------------------------------------------------------------
  1070. // Purpose:
  1071. //-----------------------------------------------------------------------------
  1072. void CWin32Surface::GetScreenSize(int &wide, int &tall)
  1073. {
  1074. if ( m_ScreenSizeOverride.m_bActive )
  1075. {
  1076. wide = m_ScreenSizeOverride.m_nValue[ 0 ];
  1077. tall = m_ScreenSizeOverride.m_nValue[ 1 ];
  1078. return;
  1079. }
  1080. VPANEL context = _embeddedPanel;
  1081. if (context)
  1082. {
  1083. wide = ::GetDeviceCaps(PLAT(context)->hdc, HORZRES);
  1084. tall = ::GetDeviceCaps(PLAT(context)->hdc, VERTRES);
  1085. }
  1086. }
  1087. bool CWin32Surface::ForceScreenSizeOverride( bool bState, int wide, int tall )
  1088. {
  1089. bool bWasSet = m_ScreenSizeOverride.m_bActive;
  1090. m_ScreenSizeOverride.m_bActive = bState;
  1091. m_ScreenSizeOverride.m_nValue[ 0 ] = wide;
  1092. m_ScreenSizeOverride.m_nValue[ 1 ] = tall;
  1093. return bWasSet;
  1094. }
  1095. // LocalToScreen, ParentLocalToScreen fixups for explicit PaintTraverse calls on Panels not at 0, 0 position
  1096. bool CWin32Surface::ForceScreenPosOffset( bool bState, int x, int y )
  1097. {
  1098. bool bWasSet = m_ScreenPosOverride.m_bActive;
  1099. m_ScreenPosOverride.m_bActive = bState;
  1100. m_ScreenPosOverride.m_nValue[ 0 ] = x;
  1101. m_ScreenPosOverride.m_nValue[ 1 ] = y;
  1102. return bWasSet;
  1103. }
  1104. void CWin32Surface::OffsetAbsPos( int &x, int &y )
  1105. {
  1106. if ( !m_ScreenPosOverride.m_bActive )
  1107. return;
  1108. x += m_ScreenPosOverride.m_nValue[ 0 ];
  1109. y += m_ScreenPosOverride.m_nValue[ 1 ];
  1110. }
  1111. bool CWin32Surface::IsScreenSizeOverrideActive( void )
  1112. {
  1113. return ( m_ScreenSizeOverride.m_bActive );
  1114. }
  1115. bool CWin32Surface::IsScreenPosOverrideActive( void )
  1116. {
  1117. return ( m_ScreenPosOverride.m_bActive );
  1118. }
  1119. void CWin32Surface::DestroyTextureID( int id )
  1120. {
  1121. // not implemented
  1122. }
  1123. int CWin32Surface::GetTextureNumFrames( int id )
  1124. {
  1125. // not implemented
  1126. return 0;
  1127. }
  1128. void CWin32Surface::DrawSetTextureFrame( int id, int nFrame, unsigned int *pFrameCache )
  1129. {
  1130. // not implemented
  1131. }
  1132. void CWin32Surface::DrawTexturedRectEx( DrawTexturedRectParms_t *pDrawParms )
  1133. {
  1134. // not implemented
  1135. }
  1136. void CWin32Surface::GetClipRect( int &x0, int &y0, int &x1, int &y1 )
  1137. {
  1138. ((VPanel *)_currentContextPanel)->Client()->GetClipRect(x0,y0,x1,y1);
  1139. }
  1140. void CWin32Surface::SetClipRect( int x0, int y0, int x1, int y1 )
  1141. {
  1142. ::SetRectRgn( PLAT(_currentContextPanel)->clipRgn,x0,y0,x1,y1);
  1143. }
  1144. //-----------------------------------------------------------------------------
  1145. // Purpose:
  1146. //-----------------------------------------------------------------------------
  1147. VPANEL CWin32Surface::GetNotifyPanel()
  1148. {
  1149. return _notifyPanel;
  1150. }
  1151. //-----------------------------------------------------------------------------
  1152. // Purpose:
  1153. //-----------------------------------------------------------------------------
  1154. void CWin32Surface::SetNotifyIcon(VPANEL context, HTexture iconID, VPANEL panelToReceiveMessages, const char *text)
  1155. {
  1156. context = GetContextPanelForChildPanel(context);
  1157. if (!context)
  1158. return;
  1159. if (!text)
  1160. {
  1161. text = "";
  1162. }
  1163. // things haven't changed so just update the tooltip
  1164. if (_notifyIcon == iconID && _notifyPanel == panelToReceiveMessages && context && PLAT(context)->notifyIcon)
  1165. {
  1166. ::NOTIFYICONDATA iconData =
  1167. {
  1168. sizeof(iconData),
  1169. PLAT(context)->hwnd,
  1170. 1, // icon ID
  1171. NIF_TIP, // modify tooltip only
  1172. WM_MY_TRAY_NOTIFICATION, // callback message
  1173. PLAT(context)->notifyIcon, // icon handle
  1174. "", // tooltip text
  1175. };
  1176. strncpy(iconData.szTip, text, 63);
  1177. iconData.szTip[63] = '\0';
  1178. ::Shell_NotifyIcon(NIM_MODIFY, &iconData);
  1179. return;
  1180. }
  1181. _notifyIcon = iconID;
  1182. _notifyPanel = panelToReceiveMessages;
  1183. DWORD dwMessage = NIM_MODIFY;
  1184. if (!iconID)
  1185. {
  1186. dwMessage = NIM_DELETE;
  1187. PLAT(context)->notifyIcon = NULL;
  1188. }
  1189. else if (!PLAT(context)->notifyIcon)
  1190. {
  1191. dwMessage = NIM_ADD;
  1192. }
  1193. // make sure the icon has been loaded
  1194. Texture *texture = NULL;
  1195. if (iconID)
  1196. {
  1197. texture = GetTextureById(iconID);
  1198. if (!texture->_icon)
  1199. {
  1200. // generate an icon for the texture
  1201. staticGenerateIconForTexture(texture, PLAT(_currentContextPanel)->hdc);
  1202. }
  1203. }
  1204. // get the icon
  1205. if (texture)
  1206. {
  1207. PLAT(context)->notifyIcon = texture->_icon;
  1208. }
  1209. ::NOTIFYICONDATA iconData =
  1210. {
  1211. sizeof(iconData),
  1212. PLAT(context)->hwnd,
  1213. 1, // icon ID
  1214. NIF_ICON | NIF_TIP | NIF_MESSAGE, // items used
  1215. WM_MY_TRAY_NOTIFICATION, // callback message
  1216. PLAT(context)->notifyIcon, // icon handle
  1217. "", // tooltip text
  1218. };
  1219. strncpy(iconData.szTip, text, 63);
  1220. iconData.szTip[63] = '\0';
  1221. BOOL success = ::Shell_NotifyIcon(dwMessage, &iconData);
  1222. if (iconID && !success)
  1223. {
  1224. DWORD err = GetLastError();
  1225. Msg("error: SetNotifyIcon(%d) failed\n", err);
  1226. }
  1227. }
  1228. void CWin32Surface::DrawSetColor(int r,int g,int b,int a)
  1229. {
  1230. SetBkColor(PLAT(_currentContextPanel)->hdc,RGB(r,g,b));
  1231. }
  1232. void CWin32Surface::DrawSetColor(Color col)
  1233. {
  1234. DrawSetColor(col[0], col[1], col[2], col[3]);
  1235. }
  1236. void CWin32Surface::DrawSetTextPos(int x, int y)
  1237. {
  1238. MoveToEx(PLAT(_currentContextPanel)->hdc,x,y,0);
  1239. m_TextPos[0] = x;
  1240. m_TextPos[1] = y;
  1241. }
  1242. void CWin32Surface::DrawGetTextPos(int& x,int& y)
  1243. {
  1244. x = m_TextPos[0];
  1245. y = m_TextPos[1];
  1246. }
  1247. void CWin32Surface::DrawSetTextFont(HFont font)
  1248. {
  1249. Assert(font);
  1250. // make the font current
  1251. m_hCurrentFont = font;
  1252. // m_FontAmalgams[m_hCurrentFont].GetFontForChar('a')->SetAsActiveFont(_currentContextPanel->Plat()->hdc);
  1253. }
  1254. void CWin32Surface::DrawFilledRect(int x0,int y0,int x1,int y1)
  1255. {
  1256. // trick to draw filled rectangles using current background color
  1257. RECT rect = { x0, y0, x1, y1};
  1258. ExtTextOut(PLAT(_currentContextPanel)->hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
  1259. }
  1260. void CWin32Surface::DrawFilledRectArray( IntRect *pRects, int numRects )
  1261. {
  1262. int i;
  1263. for( i = 0; i < numRects; i++ )
  1264. {
  1265. DrawFilledRect( pRects[i].x0, pRects[i].y0, pRects[i].x1, pRects[i].y1 );
  1266. }
  1267. }
  1268. void CWin32Surface::DrawOutlinedRect(int x0,int y0,int x1,int y1)
  1269. {
  1270. // draw an outline of a rectangle using 4 filledRect
  1271. DrawFilledRect(x0,y0,x1,y0+1); // top
  1272. DrawFilledRect(x0,y1-1,x1,y1); // bottom
  1273. DrawFilledRect(x0,y0+1,x0+1,y1-1); // left
  1274. DrawFilledRect(x1-1,y0+1,x1,y1-1); // right
  1275. }
  1276. void CWin32Surface::DrawLine(int x0,int y0,int x1,int y1)
  1277. {
  1278. POINT pt[2];
  1279. CONST POINT *p=pt;
  1280. pt[0].x=x0;
  1281. pt[0].y=y0;
  1282. pt[1].x=x1;
  1283. pt[1].y=y1;
  1284. // MoveToEx(_currentContextPanel->Plat()->hdc,x0,y0,NULL);
  1285. // LineTo(_currentContextPanel->Plat()->hdc,x1,y1);
  1286. Polyline(PLAT(_currentContextPanel)->hdc,p , 2);
  1287. }
  1288. void CWin32Surface::DrawPolyLine(int *px, int *py, int numPoints)
  1289. {
  1290. POINT *pt;
  1291. pt = (POINT *)malloc(sizeof(POINT) * numPoints);
  1292. if(pt)
  1293. {
  1294. for(int i=0;i<numPoints;i++)
  1295. {
  1296. pt[i].x= px[i];
  1297. pt[i].y= py[i];
  1298. }
  1299. Polyline(PLAT(_currentContextPanel)->hdc, pt , numPoints);
  1300. free(pt);
  1301. }
  1302. }
  1303. void CWin32Surface::DrawSetTextColor(int r,int g,int b,int a)
  1304. {
  1305. // set the draw color for lines
  1306. SetLineColor(Color(r,g,b,a));
  1307. SetTextColor(PLAT(_currentContextPanel)->hdc,RGB(r,g,b));
  1308. }
  1309. void CWin32Surface::DrawSetTextColor(Color col)
  1310. {
  1311. // set the draw color for lines
  1312. SetLineColor(col);
  1313. // end then for text
  1314. DrawSetTextColor(col[0], col[1], col[2], col[3]);
  1315. }
  1316. void CWin32Surface::SetLineColor(Color col)
  1317. {
  1318. HPEN tmp=pen;
  1319. pen = CreatePen(PS_SOLID,0,RGB(col[0], col[1], col[2]));
  1320. if(pen)
  1321. {
  1322. SelectObject(PLAT(_currentContextPanel)->hdc, pen );
  1323. }
  1324. // you must delete the pen AFTER a new one is selected
  1325. if(tmp)
  1326. {
  1327. DeleteObject(tmp);
  1328. }
  1329. }
  1330. void CWin32Surface::DrawPrintText(const wchar_t *text, int textLen, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT*/)
  1331. {
  1332. Assert(text);
  1333. if (!text)
  1334. return;
  1335. if (textLen < 1)
  1336. return;
  1337. for (int i = 0; i < textLen; i++)
  1338. {
  1339. DrawUnicodeChar(text[i]);
  1340. }
  1341. // ExtTextOut(_currentContextPanel->Plat()->hdc, 0, 0, 0, NULL, text, textLen, NULL);
  1342. }
  1343. void CWin32Surface::DrawUnicodeString( const wchar_t *pwString, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT*/)
  1344. {
  1345. Assert( pwString );
  1346. if ( !pwString )
  1347. return;
  1348. while ( wchar_t ch = *pwString++ )
  1349. {
  1350. DrawUnicodeChar( ch );
  1351. }
  1352. }
  1353. //-----------------------------------------------------------------------------
  1354. // Purpose: draws single unicode character at the current position with the
  1355. // current font & color
  1356. //-----------------------------------------------------------------------------
  1357. void CWin32Surface::DrawUnicodeChar(wchar_t wch, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT*/)
  1358. {
  1359. // set the current font
  1360. CWin32Font *winFont = FontManager().GetFontForChar(m_hCurrentFont, wch);
  1361. if (!winFont)
  1362. return;
  1363. if (m_pActiveFont != winFont)
  1364. {
  1365. winFont->SetAsActiveFont(PLAT(_currentContextPanel)->hdc);
  1366. m_pActiveFont = winFont;
  1367. }
  1368. if (m_bSupportsUnicode)
  1369. {
  1370. ExtTextOutW(PLAT(_currentContextPanel)->hdc, 0, 0, 0, NULL, &wch, 1, NULL);
  1371. }
  1372. else
  1373. {
  1374. char mbcs[6] = { 0 };
  1375. ::WideCharToMultiByte(CP_ACP, 0, &wch, 1, mbcs, sizeof(mbcs), NULL, NULL);
  1376. ExtTextOutA(PLAT(_currentContextPanel)->hdc, 0, 0, 0, NULL, mbcs, strlen(mbcs), NULL);
  1377. }
  1378. }
  1379. //-----------------------------------------------------------------------------
  1380. // Purpose: allocates a new texture id
  1381. //-----------------------------------------------------------------------------
  1382. int CWin32Surface::CreateNewTextureID( bool procedural )
  1383. {
  1384. //!! hack, arbitrary base
  1385. static int staticBindIndex = 2700;
  1386. return staticBindIndex++;
  1387. }
  1388. //-----------------------------------------------------------------------------
  1389. // Purpose: returns true if the texture id has a valid texture bound to it
  1390. //-----------------------------------------------------------------------------
  1391. bool CWin32Surface::IsTextureIDValid(int id)
  1392. {
  1393. return (GetTextureById(id) != NULL);
  1394. }
  1395. //-----------------------------------------------------------------------------
  1396. // Purpose: clear up alloced resources on a texture
  1397. //-----------------------------------------------------------------------------
  1398. void CWin32Surface::FreeTextureData( vgui::Texture *pTexture )
  1399. {
  1400. if ( pTexture->_bitmap )
  1401. {
  1402. ::DeleteObject( pTexture->_bitmap );
  1403. }
  1404. // if ( pTexture->m_bitmapScaled )
  1405. // {
  1406. // ::DeleteObject( pTexture->m_bitmapScaled );
  1407. // }
  1408. if ( pTexture->_maskBitmap )
  1409. {
  1410. ::DeleteObject( pTexture->_maskBitmap );
  1411. }
  1412. if ( pTexture->_icon )
  1413. {
  1414. ::DestroyIcon( pTexture->_icon );
  1415. }
  1416. // if ( pTexture->rgba )
  1417. // delete[] pTexture->rgba;
  1418. }
  1419. //-----------------------------------------------------------------------------
  1420. // Purpose: returns true if the texture id has a valid texture bound to it
  1421. //-----------------------------------------------------------------------------
  1422. bool CWin32Surface::DeleteTextureByID(int id)
  1423. {
  1424. #if defined( PS3OVERLAYUI_EXPORTS )
  1425. AUTO_LOCK( m_MutexTextureData );
  1426. #endif
  1427. Texture findTex = { id };
  1428. int index = m_VGuiSurfaceTextures.Find(findTex);
  1429. if (m_VGuiSurfaceTextures.IsValidIndex(index))
  1430. {
  1431. Texture *texture = &m_VGuiSurfaceTextures[index];
  1432. FreeTextureData( texture );
  1433. m_VGuiSurfaceTextures.RemoveAt(index);
  1434. return true;
  1435. }
  1436. return false;
  1437. }
  1438. //-----------------------------------------------------------------------------
  1439. // Purpose: does nothing, since we don't need this optimization in win32
  1440. //-----------------------------------------------------------------------------
  1441. void CWin32Surface::DrawFlushText()
  1442. {
  1443. }
  1444. //-----------------------------------------------------------------------------
  1445. // Purpose: Load the chrome dll an init the interface if needed
  1446. //-----------------------------------------------------------------------------
  1447. bool CWin32Surface::LoadChromeHTML()
  1448. {
  1449. return false;
  1450. }
  1451. //-----------------------------------------------------------------------------
  1452. // Purpose: create a html helper object
  1453. //-----------------------------------------------------------------------------
  1454. IHTML *CWin32Surface::CreateHTMLWindow(vgui::IHTMLEvents *events, VPANEL context )
  1455. {
  1456. if ( !LoadChromeHTML() )
  1457. {
  1458. return NULL;
  1459. }
  1460. // setup the _currentContextPanel
  1461. VPANEL parent = GetContextPanelForChildPanel(context);
  1462. if (!parent)
  1463. return NULL;
  1464. void *pWindowHandle;
  1465. #ifdef WIN32
  1466. pWindowHandle = PLAT(parent)->hwnd;
  1467. #elif defined(OSX)
  1468. pWindowHandle = ((VPanel *)parent)->Plat()->m_hWindow;
  1469. #elif defined(LINUX)
  1470. pWindowHandle = ((VPanel *)parent)->Plat()->m_hWindow;
  1471. #endif
  1472. return NULL;
  1473. }
  1474. //-----------------------------------------------------------------------------
  1475. // Purpose: delete an html helper object
  1476. //-----------------------------------------------------------------------------
  1477. void CWin32Surface::DeleteHTMLWindow(IHTML *htmlwin)
  1478. {
  1479. }
  1480. //-----------------------------------------------------------------------------
  1481. // Purpose: tell a html window to update its backing texture
  1482. //-----------------------------------------------------------------------------
  1483. void CWin32Surface::PaintHTMLWindow(IHTML *htmlwin)
  1484. {
  1485. }
  1486. //-----------------------------------------------------------------------------
  1487. void CWin32Surface::SetAllowHTMLJavaScript( bool state )
  1488. {
  1489. if ( !LoadChromeHTML() )
  1490. {
  1491. return;
  1492. }
  1493. }
  1494. //-----------------------------------------------------------------------------
  1495. // Purpose: sets the current active texture
  1496. //-----------------------------------------------------------------------------
  1497. void CWin32Surface::DrawSetTexture(int id)
  1498. {
  1499. Texture *texture = GetTextureById(id);
  1500. m_pCurrentTexture = texture;
  1501. }
  1502. HBITMAP staticCreateBitmapHandle(int wide, int tall, HDC hdc, int bpp, void **dib);
  1503. //-----------------------------------------------------------------------------
  1504. // Purpose: maps a texture from memory to an id, and uploads it into the engine
  1505. //-----------------------------------------------------------------------------
  1506. void CWin32Surface::DrawSetTextureRGBA( int id, const unsigned char* rgba, int wide, int tall )
  1507. {
  1508. DrawSetTextureRGBAEx( id, rgba, wide, tall, IMAGE_FORMAT_RGBA8888 );
  1509. }
  1510. //-----------------------------------------------------------------------------
  1511. // Purpose: maps a texture from memory to an id, and uploads it into the engine
  1512. //-----------------------------------------------------------------------------
  1513. void CWin32Surface::DrawSetTextureRGBALinear( int id, const unsigned char* rgba, int wide, int tall )
  1514. {
  1515. DrawSetTextureRGBAEx( id, rgba, wide, tall, IMAGE_FORMAT_RGBA8888 );
  1516. }
  1517. //-----------------------------------------------------------------------------
  1518. // Purpose: maps a texture from memory to an id, and uploads it into the engine
  1519. //-----------------------------------------------------------------------------
  1520. void CWin32Surface::DrawSetTextureRGBAEx( int id, const unsigned char* rgba, int wide, int tall, ImageFormat imageFormat )
  1521. {
  1522. Texture *texture = GetTextureById(id);
  1523. if (texture)
  1524. {
  1525. if (texture->_bitmap)
  1526. {
  1527. ::DeleteObject(texture->_bitmap);
  1528. }
  1529. if (texture->_maskBitmap)
  1530. {
  1531. ::DeleteObject(texture->_maskBitmap);
  1532. }
  1533. }
  1534. if (!texture)
  1535. {
  1536. // allocate a new texture
  1537. texture = AllocTextureForId(id);
  1538. memset(texture, 0, sizeof(Texture));
  1539. }
  1540. {
  1541. // no texture or forced load the new texture
  1542. texture->_id = id;
  1543. texture->_filename =NULL;
  1544. texture->_wide = wide;
  1545. texture->_tall = tall;
  1546. texture->_icon = NULL;
  1547. texture->_dib = NULL;
  1548. texture->_bitmap = staticCreateBitmapHandle(texture->_wide,
  1549. texture->_tall, PLAT(_currentContextPanel)->hdc, 32, &texture->_dib );
  1550. // copy over the texture data
  1551. memcpy(texture->_dib,rgba,wide*tall*4);
  1552. }
  1553. m_pCurrentTexture = texture;
  1554. }
  1555. //-----------------------------------------------------------------------------
  1556. // Purpose:
  1557. // Input : id -
  1558. // *filename -
  1559. // maxlen -
  1560. // Output : Returns true on success, false on failure.
  1561. //-----------------------------------------------------------------------------
  1562. bool CWin32Surface::DrawGetTextureFile(int id, char *filename, int maxlen )
  1563. {
  1564. Texture *texture = GetTextureById(id);
  1565. if ( !texture )
  1566. return false;
  1567. Q_strncpy( filename, texture->_filename, maxlen );
  1568. return true;
  1569. }
  1570. int CWin32Surface::DrawGetTextureId( char const *filename )
  1571. {
  1572. int i = m_VGuiSurfaceTextures.FirstInorder();
  1573. while ( i != m_VGuiSurfaceTextures.InvalidIndex() )
  1574. {
  1575. Texture *texture = &m_VGuiSurfaceTextures[i];
  1576. if ( !Q_stricmp( filename, texture->_filename ) )
  1577. return texture->_id;
  1578. i = m_VGuiSurfaceTextures.NextInorder( i );
  1579. }
  1580. return -1;
  1581. }
  1582. //-----------------------------------------------------------------------------
  1583. // Purpose: Maps a texture file to an id, and makes it the current drawing texture
  1584. // tries to load as a .tga first, and if not found as a .bmp
  1585. //-----------------------------------------------------------------------------
  1586. void CWin32Surface::DrawSetTextureFile(int id, const char *filename, int hardwareFilter, bool forceReload /*= false*/)
  1587. {
  1588. Texture *texture = GetTextureById(id);
  1589. if (!texture || stricmp(filename, texture->_filename) || forceReload )
  1590. {
  1591. // no texture, or the filename is different; load the new texture
  1592. if (!texture)
  1593. {
  1594. // allocate a new texture
  1595. texture = AllocTextureForId(id);
  1596. memset(texture, 0, sizeof(Texture));
  1597. }
  1598. if (texture)
  1599. {
  1600. if (texture->_bitmap)
  1601. {
  1602. ::DeleteObject(texture->_bitmap);
  1603. }
  1604. if (texture->_maskBitmap)
  1605. {
  1606. ::DeleteObject(texture->_maskBitmap);
  1607. }
  1608. }
  1609. texture->_id = id;
  1610. texture->_filename = filename;
  1611. // try and find the file
  1612. bool success = LoadTGA(texture, filename);
  1613. if (!success)
  1614. {
  1615. // strip off the vgui/ and try again
  1616. const char *psz = Q_stristr(filename, "vgui/");
  1617. if (psz)
  1618. {
  1619. success = LoadTGA(texture, filename + strlen("vgui/"));
  1620. }
  1621. }
  1622. if (!success)
  1623. {
  1624. Msg("Error: texture file '%s' does not exist or is invalid\n", filename);
  1625. return;
  1626. }
  1627. }
  1628. m_pCurrentTexture = texture;
  1629. }
  1630. //-----------------------------------------------------------------------------
  1631. // Purpose:
  1632. //-----------------------------------------------------------------------------
  1633. void CWin32Surface::DrawTexturedRect(int x0,int y0,int x1,int y1)
  1634. {
  1635. if (m_pCurrentTexture == 0)
  1636. {
  1637. return;
  1638. }
  1639. if (PLAT(_currentContextPanel)->textureDC == 0)
  1640. {
  1641. return;
  1642. }
  1643. HBITMAP bitmap = m_pCurrentTexture->_bitmap;
  1644. int wide = m_pCurrentTexture->_wide;
  1645. int tall = m_pCurrentTexture->_tall;
  1646. HGDIOBJ oldObject;
  1647. if (m_pCurrentTexture->_bMask)
  1648. {
  1649. HBITMAP bitmap_mask = m_pCurrentTexture->_maskBitmap;
  1650. // draw the mask first to clear out the background to black
  1651. oldObject = ::SelectObject(PLAT(_currentContextPanel)->textureDC, bitmap_mask);
  1652. ::StretchBlt(PLAT(_currentContextPanel)->hdc,x0,y0,x1-x0,y1-y0,PLAT(_currentContextPanel)->textureDC,0,0,wide,tall,SRCAND);
  1653. // draw over the 'black areas' with the bitmap
  1654. ::SelectObject(PLAT(_currentContextPanel)->textureDC, bitmap);
  1655. ::StretchBlt(PLAT(_currentContextPanel)->hdc,x0,y0,x1-x0,y1-y0,PLAT(_currentContextPanel)->textureDC,0,0,wide,tall,SRCPAINT);
  1656. }
  1657. else
  1658. {
  1659. oldObject = ::SelectObject(PLAT(_currentContextPanel)->textureDC, bitmap);
  1660. ::StretchBlt(PLAT(_currentContextPanel)->hdc,x0,y0,x1-x0,y1-y0,PLAT(_currentContextPanel)->textureDC,0,0,wide,tall,SRCCOPY);
  1661. }
  1662. ::SelectObject(PLAT(_currentContextPanel)->textureDC, oldObject);
  1663. // test code, should be used in win98/win2k for true alpha
  1664. // BLENDFUNCTION blendFunction = { AC_SRC_OVER, 0, 255, 0 };
  1665. // ::AlphaBlend(PLAT(_currentContextPanel)->hdc,x0,y0,x1-x0,y1-y0,PLAT(_currentContextPanel)->textureDC,0,0,wide,tall,blendFunction);
  1666. }
  1667. //-----------------------------------------------------------------------------
  1668. // Purpose: Called by vgui to get texture dimensions
  1669. //-----------------------------------------------------------------------------
  1670. void CWin32Surface::DrawGetTextureSize(int id, int &wide, int &tall)
  1671. {
  1672. Texture *texture = GetTextureById(id);
  1673. if (!texture)
  1674. return;
  1675. wide = texture->_wide;
  1676. tall = texture->_tall;
  1677. }
  1678. #pragma pack(1)
  1679. typedef struct
  1680. {
  1681. unsigned char id_length, colormap_type, image_type;
  1682. unsigned short colormap_index, colormap_length;
  1683. unsigned char colormap_size;
  1684. unsigned short x_origin, y_origin, width, height;
  1685. unsigned char pixel_size, attributes;
  1686. } tga_header_t;
  1687. #pragma pack()
  1688. HBITMAP staticCreateBitmapHandle(int wide, int tall, HDC hdc, int bpp, void **dib)
  1689. {
  1690. BITMAPINFOHEADER bitmapInfoHeader;
  1691. memset(&bitmapInfoHeader, 0, sizeof(bitmapInfoHeader));
  1692. bitmapInfoHeader.biSize = sizeof(bitmapInfoHeader);
  1693. bitmapInfoHeader.biWidth = wide;
  1694. bitmapInfoHeader.biHeight = -tall;
  1695. bitmapInfoHeader.biPlanes = 1;
  1696. bitmapInfoHeader.biBitCount = bpp;
  1697. bitmapInfoHeader.biCompression = BI_RGB;
  1698. HBITMAP hRet;
  1699. hRet = CreateDIBSection(hdc, (BITMAPINFO*)&bitmapInfoHeader, DIB_RGB_COLORS, dib, 0, 0);
  1700. if ( !hRet )
  1701. Error( "staticCreateBitmapHandle: can't create DIB" );
  1702. return hRet;
  1703. }
  1704. #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
  1705. //-----------------------------------------------------------------------------
  1706. // Purpose:
  1707. //-----------------------------------------------------------------------------
  1708. bool CWin32Surface::LoadBMP(Texture *texture, const char *filename)
  1709. {
  1710. // try load the tga
  1711. char buf[1024];
  1712. _snprintf(buf, sizeof(buf), "%s.bmp", filename);
  1713. // look in the skins directory first
  1714. FileHandle_t file = g_pFullFileSystem->Open(buf, "rb", "SKIN");
  1715. if (!file)
  1716. {
  1717. file = g_pFullFileSystem->Open(buf, "rb", NULL);
  1718. }
  1719. if (!file)
  1720. return false;
  1721. bool success = false;
  1722. // Parse bitmap
  1723. BITMAPFILEHEADER bmfHeader;
  1724. DWORD dwBitsSize, dwFileSize;
  1725. LPBITMAPINFO lpbmi;
  1726. dwFileSize = g_pFullFileSystem->Size( file );
  1727. g_pFullFileSystem->Read( &bmfHeader, sizeof(bmfHeader), file );
  1728. if (bmfHeader.bfType == DIB_HEADER_MARKER)
  1729. {
  1730. dwBitsSize = dwFileSize - sizeof(bmfHeader);
  1731. HGLOBAL hDIB = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize );
  1732. char *pDIB = (LPSTR)::GlobalLock((HGLOBAL)hDIB);
  1733. {
  1734. int i, j;
  1735. g_pFullFileSystem->Read(pDIB, dwBitsSize, file );
  1736. lpbmi = (LPBITMAPINFO)pDIB;
  1737. // we now have a block of memory, rgba
  1738. // throw a bitmap header on it and register it in windows
  1739. texture->_wide = lpbmi->bmiHeader.biWidth;
  1740. texture->_tall = lpbmi->bmiHeader.biHeight;
  1741. texture->_icon = NULL;
  1742. texture->_bMask = false;
  1743. texture->_bitmap = staticCreateBitmapHandle(
  1744. texture->_wide,
  1745. texture->_tall,
  1746. PLAT(_currentContextPanel)->hdc,
  1747. 32, &texture->_dib );
  1748. unsigned char *rgba = (unsigned char *)( pDIB + sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD ) );
  1749. // Copy raw data
  1750. for (j = 0; j < texture->_tall; j++)
  1751. {
  1752. for (i = 0; i <texture->_wide; i++)
  1753. {
  1754. int y = (texture->_tall - j - 1);
  1755. int offs = ( y * texture->_wide + i);
  1756. int offsdest = (j * texture->_wide + i) * 4;
  1757. unsigned char *src = ((unsigned char *)rgba) + offs;
  1758. char *dst = ((char*)texture->_dib) + offsdest;
  1759. dst[0] = lpbmi->bmiColors[ *src ].rgbRed;
  1760. dst[1] = lpbmi->bmiColors[ *src ].rgbGreen;
  1761. dst[2] = lpbmi->bmiColors[ *src ].rgbBlue;
  1762. dst[3] = (unsigned char)255;
  1763. }
  1764. }
  1765. success = true;
  1766. }
  1767. ::GlobalUnlock( hDIB);
  1768. ::GlobalFree((HGLOBAL) hDIB);
  1769. }
  1770. g_pFullFileSystem->Close(file);
  1771. return success;
  1772. }
  1773. //-----------------------------------------------------------------------------
  1774. // Purpose:
  1775. //-----------------------------------------------------------------------------
  1776. bool CWin32Surface::LoadTGA(Texture *texture, const char *filename)
  1777. {
  1778. bool invertAlpha = false;
  1779. // try load the tga
  1780. char buf[1024];
  1781. _snprintf(buf, sizeof(buf), "%s.tga", filename);
  1782. // look in the skins directory first
  1783. FileHandle_t file = g_pFullFileSystem->Open(buf, "rb", "SKIN");
  1784. if (!file)
  1785. {
  1786. file = g_pFullFileSystem->Open(buf, "rb", NULL);
  1787. }
  1788. if (!file)
  1789. {
  1790. return LoadBMP( texture, filename );
  1791. }
  1792. // read the header
  1793. tga_header_t tgaHeader;
  1794. g_pFullFileSystem->Read(&tgaHeader, sizeof(tgaHeader), file);
  1795. if (tgaHeader.image_type != 2 && tgaHeader.image_type != 10)
  1796. {
  1797. g_pIVgui->DPrintf2("Error: texture file '%s' has invalid image_type %d\n", filename, tgaHeader.image_type);
  1798. return false;
  1799. }
  1800. if (tgaHeader.colormap_type != 0)
  1801. {
  1802. return false;
  1803. }
  1804. if (tgaHeader.pixel_size != 24 && tgaHeader.pixel_size !=32)
  1805. {
  1806. return false;
  1807. }
  1808. if (tgaHeader.id_length != 0)
  1809. {
  1810. g_pFullFileSystem->Seek( file, tgaHeader.id_length, FILESYSTEM_SEEK_CURRENT );
  1811. }
  1812. // allocate memory for the destination
  1813. uchar *rgba = (unsigned char *)malloc(tgaHeader.width * tgaHeader.height * 4);
  1814. int column, row;
  1815. uchar *ptr;
  1816. bool bMask = false;
  1817. if (tgaHeader.image_type == 2)
  1818. {
  1819. for (row = tgaHeader.height - 1; row >= 0; row--)
  1820. {
  1821. ptr = ((uchar *)rgba) + (row * tgaHeader.width * 4);
  1822. for (column = 0; column < tgaHeader.width; column++)
  1823. {
  1824. switch (tgaHeader.pixel_size)
  1825. {
  1826. case 24:
  1827. {
  1828. g_pFullFileSystem->Read(ptr + 2, 1, file);
  1829. g_pFullFileSystem->Read(ptr + 1, 1, file);
  1830. g_pFullFileSystem->Read(ptr + 0, 1, file);
  1831. ptr[3] = 255;
  1832. if (invertAlpha)
  1833. {
  1834. ptr[3] = 0;
  1835. }
  1836. ptr += 4;
  1837. break;
  1838. }
  1839. case 32:
  1840. {
  1841. g_pFullFileSystem->Read(ptr + 2, 1, file);
  1842. g_pFullFileSystem->Read(ptr + 1, 1, file);
  1843. g_pFullFileSystem->Read(ptr + 0, 1, file);
  1844. g_pFullFileSystem->Read(ptr + 3, 1, file);
  1845. if (!invertAlpha)
  1846. {
  1847. // if it's 0, then it's going to be zeroed out
  1848. if (ptr[3] == 0)
  1849. {
  1850. ptr[3] = 255;
  1851. }
  1852. else
  1853. {
  1854. // anything besides 0 will be shown
  1855. ptr[3] = 0;
  1856. }
  1857. //ptr[3] = 255 - ptr[3];
  1858. }
  1859. bMask = true;
  1860. ptr += 4;
  1861. break;
  1862. }
  1863. }
  1864. }
  1865. }
  1866. }
  1867. else
  1868. {
  1869. uchar packetHeader, packetSize, j, color[4];
  1870. for(row = tgaHeader.height - 1; row >= 0; row--)
  1871. {
  1872. ptr = ((uchar*)rgba) + row * tgaHeader.width * 4;
  1873. for(column=0;column<tgaHeader.width;)
  1874. {
  1875. g_pFullFileSystem->Read(&packetHeader, 1, file);
  1876. packetSize = 1 + (packetHeader & 0x7f);
  1877. if (packetHeader & 0x80)
  1878. {
  1879. switch (tgaHeader.pixel_size)
  1880. {
  1881. case 24:
  1882. {
  1883. g_pFullFileSystem->Read(color + 2, 1, file);
  1884. g_pFullFileSystem->Read(color + 1, 1, file);
  1885. g_pFullFileSystem->Read(color + 0, 1, file);
  1886. if (invertAlpha)
  1887. {
  1888. color[3] = 0;
  1889. }
  1890. else
  1891. {
  1892. color[3] = 255;
  1893. }
  1894. break;
  1895. }
  1896. case 32:
  1897. {
  1898. g_pFullFileSystem->Read(color + 2, 1, file);
  1899. g_pFullFileSystem->Read(color + 1, 1, file);
  1900. g_pFullFileSystem->Read(color + 0, 1, file);
  1901. g_pFullFileSystem->Read(color + 3, 1, file);
  1902. bMask = true;
  1903. if (invertAlpha)
  1904. {
  1905. color[3] = 255 - color[3];
  1906. }
  1907. break;
  1908. }
  1909. }
  1910. for (j = 0; j < packetSize; j++)
  1911. {
  1912. ptr[0] = color[0];
  1913. ptr[1] = color[1];
  1914. ptr[2] = color[2];
  1915. ptr[3] = color[3];
  1916. ptr += 4;
  1917. column++;
  1918. if (column == tgaHeader.width)
  1919. {
  1920. column = 0;
  1921. if (row > 0)
  1922. {
  1923. row--;
  1924. }
  1925. else
  1926. {
  1927. goto breakOut;
  1928. }
  1929. ptr = ((uchar*)rgba) + (row * tgaHeader.width * 4);
  1930. }
  1931. }
  1932. }
  1933. else
  1934. {
  1935. for (j = 0; j < packetSize; j++)
  1936. {
  1937. switch (tgaHeader.pixel_size)
  1938. {
  1939. case 24:
  1940. {
  1941. g_pFullFileSystem->Read(ptr + 2, 1, file);
  1942. g_pFullFileSystem->Read(ptr + 1, 1, file);
  1943. g_pFullFileSystem->Read(ptr + 0, 1, file);
  1944. ptr[3] = 255;
  1945. if (invertAlpha)
  1946. {
  1947. ptr[3] = 0;
  1948. }
  1949. else
  1950. {
  1951. ptr[3] = 255;
  1952. }
  1953. ptr += 4;
  1954. break;
  1955. }
  1956. case 32:
  1957. {
  1958. g_pFullFileSystem->Read(ptr + 2, 1, file);
  1959. g_pFullFileSystem->Read(ptr + 1, 1, file);
  1960. g_pFullFileSystem->Read(ptr + 0, 1, file);
  1961. g_pFullFileSystem->Read(ptr + 3, 1, file);
  1962. if (invertAlpha)
  1963. {
  1964. ptr[3]=255-ptr[3];
  1965. }
  1966. ptr += 4;
  1967. break;
  1968. }
  1969. }
  1970. column++;
  1971. if (column == tgaHeader.width)
  1972. {
  1973. column = 0;
  1974. if(row > 0)
  1975. {
  1976. row--;
  1977. }
  1978. else
  1979. {
  1980. goto breakOut;
  1981. }
  1982. ptr = ((uchar*)rgba) + row * tgaHeader.width * 4;
  1983. }
  1984. }
  1985. }
  1986. }
  1987. }
  1988. breakOut:;
  1989. }
  1990. g_pFullFileSystem->Close(file);
  1991. // we now have a block of memory, rgba
  1992. // throw a bitmap header on it and register it in windows
  1993. texture->_wide = tgaHeader.width;
  1994. texture->_tall = tgaHeader.height;
  1995. texture->_icon = NULL;
  1996. texture->_bitmap = staticCreateBitmapHandle(tgaHeader.width, tgaHeader.height, PLAT(_currentContextPanel)->hdc, 32, &texture->_dib);
  1997. texture->_bMask = bMask;
  1998. if (bMask)
  1999. texture->_maskBitmap = staticCreateBitmapHandle(tgaHeader.width, tgaHeader.height, PLAT(_currentContextPanel)->hdc, 32, &texture->_maskDib);
  2000. else
  2001. texture->_maskBitmap = NULL;
  2002. for (int j = 0; j < texture->_tall; j++)
  2003. {
  2004. for (int i = 0; i < texture->_wide; i++)
  2005. {
  2006. int offs = (j * texture->_wide + i) * 4;
  2007. char *src = ((char*)rgba) + offs;
  2008. char *dst = ((char*)texture->_dib) + offs;
  2009. if (bMask)
  2010. {
  2011. char *maskDst = ((char*) texture->_maskDib) + offs;
  2012. // if there's value here, then it needs to be cleared
  2013. if (src[3])
  2014. {
  2015. // mask will be & with background, so it needs to be 0xFF
  2016. maskDst[0] = maskDst[1] = maskDst[2] = maskDst[3] = -1;;
  2017. // clear the art in the bitmap because it's not going to display and will be | with background
  2018. dst[0] = dst[1] = dst[2] = dst[3] = 0;
  2019. }
  2020. else
  2021. {
  2022. // this will clear the background before drawing this bitmap
  2023. maskDst[0] = maskDst[1] = maskDst[2] = maskDst[3] = 0x00;
  2024. // copy over the art
  2025. dst[0] = src[2];
  2026. dst[1] = src[1];
  2027. dst[2] = src[0];
  2028. dst[3] = src[3];
  2029. }
  2030. }
  2031. else
  2032. {
  2033. dst[0] = src[2];
  2034. dst[1] = src[1];
  2035. dst[2] = src[0];
  2036. dst[3] = src[3];
  2037. }
  2038. }
  2039. }
  2040. free(rgba);
  2041. return true;
  2042. }
  2043. //-----------------------------------------------------------------------------
  2044. // Purpose: brings the current surface to the foreground
  2045. //-----------------------------------------------------------------------------
  2046. void CWin32Surface::BringToFront(VPANEL panel)
  2047. {
  2048. // force the panel to the top of the windows z-order
  2049. panel = GetContextPanelForChildPanel(panel);
  2050. if (panel && PLAT(panel))
  2051. {
  2052. // this should trigger a WM_SETFOCUS message which will move the window to the top
  2053. ::SetActiveWindow(PLAT(panel)->hwnd);
  2054. }
  2055. }
  2056. //-----------------------------------------------------------------------------
  2057. // Purpose: puts the thread that created the specified window into the foreground
  2058. // and activates the window.
  2059. //-----------------------------------------------------------------------------
  2060. void CWin32Surface::SetForegroundWindow(VPANEL panel)
  2061. {
  2062. if (panel && PLAT(panel))
  2063. {
  2064. ::SetForegroundWindow(PLAT(panel)->hwnd);
  2065. }
  2066. }
  2067. //-----------------------------------------------------------------------------
  2068. // Purpose:
  2069. //-----------------------------------------------------------------------------
  2070. void CWin32Surface::MovePopupToFront(VPANEL panel)
  2071. {
  2072. _popupList.MoveElementToEnd(panel);
  2073. g_pIVgui->PostMessage(panel, new KeyValues("OnMovedPopupToFront"), NULL);
  2074. }
  2075. //-----------------------------------------------------------------------------
  2076. // Purpose:
  2077. //-----------------------------------------------------------------------------
  2078. void CWin32Surface::MovePopupToBack(VPANEL panel)
  2079. {
  2080. }
  2081. //-----------------------------------------------------------------------------
  2082. // Purpose:
  2083. // HWND_TOPMOST - Places the window above all non-topmost windows.
  2084. // The window maintains its topmost position even when it is deactivated.
  2085. // HWND_NOTOPMOST - Places the window above all non-topmost windows (that is, behind
  2086. // all topmost windows). This flag has no effect if the window is already a non-topmost window.
  2087. //-----------------------------------------------------------------------------
  2088. void CWin32Surface::SetAsTopMost(VPANEL panel, bool state)
  2089. {
  2090. panel = GetContextPanelForChildPanel(panel);
  2091. DWORD style=SWP_NOMOVE|SWP_NOSIZE;
  2092. if (PLAT(panel)->disabled)
  2093. {
  2094. style |= SWP_NOACTIVATE;
  2095. }
  2096. if (state)
  2097. {
  2098. SetFocus(PLAT(panel)->hwnd);
  2099. SetWindowPos(PLAT(panel)->hwnd,HWND_TOPMOST,0,0,0,0,style );
  2100. }
  2101. else
  2102. {
  2103. SetWindowPos(PLAT(panel)->hwnd,HWND_NOTOPMOST,0,0,0,0,style );
  2104. }
  2105. }
  2106. //-----------------------------------------------------------------------------
  2107. // Purpose:
  2108. //-----------------------------------------------------------------------------
  2109. void CWin32Surface::SetPanelVisible(VPANEL panel, bool visible)
  2110. {
  2111. // if the panel has an attached window we need to set it's style
  2112. if (PLAT(panel))
  2113. {
  2114. if (visible)
  2115. {
  2116. // show the window
  2117. ::ShowWindow(PLAT(panel)->hwnd, SW_SHOWNA);
  2118. }
  2119. else
  2120. {
  2121. // hide the window
  2122. ::ShowWindow(PLAT(panel)->hwnd, SW_HIDE);
  2123. }
  2124. }
  2125. }
  2126. //-----------------------------------------------------------------------------
  2127. // Purpose: Flashes the window icon in the taskbar, to get the users attention
  2128. // Input : flashCount - number of times to flash the window
  2129. //-----------------------------------------------------------------------------
  2130. void CWin32Surface::FlashWindow(VPANEL panel, bool state)
  2131. {
  2132. if (!PLAT(panel))
  2133. return;
  2134. ::FlashWindow(PLAT(panel)->hwnd, state);
  2135. }
  2136. //-----------------------------------------------------------------------------
  2137. // Purpose:
  2138. //-----------------------------------------------------------------------------
  2139. void CWin32Surface::SetTopLevelFocus(VPANEL panel)
  2140. {
  2141. // this is handled by WM_FOCUS messages instead of directly
  2142. }
  2143. //-----------------------------------------------------------------------------
  2144. // Purpose:
  2145. //-----------------------------------------------------------------------------
  2146. void CWin32Surface::SetMinimized(VPANEL panel, bool state)
  2147. {
  2148. if (PLAT(panel))
  2149. {
  2150. if (state)
  2151. {
  2152. ::ShowWindow(PLAT(panel)->hwnd, SW_MINIMIZE);
  2153. }
  2154. else
  2155. {
  2156. ::ShowWindow(PLAT(panel)->hwnd, SW_SHOWNORMAL);
  2157. }
  2158. }
  2159. }
  2160. //-----------------------------------------------------------------------------
  2161. // Purpose: returns true if the window is minimized
  2162. //-----------------------------------------------------------------------------
  2163. bool CWin32Surface::IsMinimized(VPANEL panel)
  2164. {
  2165. if (PLAT(panel)->hwnd)
  2166. {
  2167. return ::IsIconic(PLAT(panel)->hwnd) ? true : false;
  2168. }
  2169. return false;
  2170. }
  2171. //-----------------------------------------------------------------------------
  2172. // Purpose:
  2173. //-----------------------------------------------------------------------------
  2174. void CWin32Surface::SetTitle(VPANEL panel, const wchar_t *title)
  2175. {
  2176. panel = GetContextPanelForChildPanel(panel);
  2177. if (panel)
  2178. {
  2179. if (m_bSupportsUnicode)
  2180. {
  2181. SetWindowTextW(PLAT(panel)->hwnd, title);
  2182. }
  2183. else
  2184. {
  2185. char mbcs[512];
  2186. ::WideCharToMultiByte(CP_ACP, 0, title, -1, mbcs, sizeof(mbcs), NULL, NULL);
  2187. SetWindowTextA(PLAT(panel)->hwnd, mbcs);
  2188. }
  2189. }
  2190. }
  2191. //-----------------------------------------------------------------------------
  2192. // Purpose:
  2193. //-----------------------------------------------------------------------------
  2194. void CWin32Surface::SetAsToolBar(VPANEL panel, bool state)
  2195. {
  2196. panel = GetContextPanelForChildPanel(panel);
  2197. if (panel && PLAT(panel))
  2198. {
  2199. if (state)
  2200. {
  2201. ::SetWindowLong(PLAT(panel)->hwnd, GWL_EXSTYLE, ::GetWindowLong(PLAT(panel)->hwnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW);
  2202. }
  2203. else
  2204. {
  2205. ::SetWindowLong(PLAT(panel)->hwnd, GWL_EXSTYLE, ::GetWindowLong(PLAT(panel)->hwnd, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW);
  2206. }
  2207. }
  2208. }
  2209. //-----------------------------------------------------------------------------
  2210. // Purpose:
  2211. //-----------------------------------------------------------------------------
  2212. int CWin32Surface::GetPopupCount()
  2213. {
  2214. return _popupList.GetCount();
  2215. }
  2216. //-----------------------------------------------------------------------------
  2217. // Purpose:
  2218. //-----------------------------------------------------------------------------
  2219. VPANEL CWin32Surface::GetPopup(int index)
  2220. {
  2221. return _popupList[index];
  2222. }
  2223. //-----------------------------------------------------------------------------
  2224. // Purpose:
  2225. //-----------------------------------------------------------------------------
  2226. void CWin32Surface::CreatePopup(VPANEL panel, bool minimised, bool showTaskbarIcon, bool disabled, bool mouseInput, bool kbInput )
  2227. {
  2228. if (((VPanel *)panel)->IsPopup() && PLAT(panel))
  2229. {
  2230. // it's already a popup so bail
  2231. return;
  2232. }
  2233. // make sure it's in the hierarchy
  2234. if (!((VPanel *)panel)->GetParent() && panel != _embeddedPanel)
  2235. {
  2236. ((VPanel *)panel)->SetParent((VPanel *)_embeddedPanel);
  2237. }
  2238. int x,y,wide,tall;
  2239. ((VPanel *)panel)->GetPos(x, y);
  2240. ((VPanel *)panel)->GetSize(wide, tall);
  2241. ((VPanel *)panel)->SetPopup(true);
  2242. ((VPanel *)panel)->SetKeyBoardInputEnabled(kbInput);
  2243. ((VPanel *)panel)->SetMouseInputEnabled(mouseInput);
  2244. // find our parent window if we have one
  2245. HWND hwndParent = NULL;
  2246. VPANEL pParent = GetContextPanelForChildPanel(panel);
  2247. if (pParent && pParent != _embeddedPanel)
  2248. {
  2249. hwndParent = PLAT(pParent)->hwnd;
  2250. }
  2251. //create the window and initialize platform specific data
  2252. //window is initial a popup and not visible
  2253. //when ApplyChanges is called the window will be shown unless
  2254. //it SetVisible(false) is called
  2255. SurfacePlat *plat = new SurfacePlat;
  2256. ((VPanel *)panel)->SetPlat(plat);
  2257. // WS_SYSMENU and WS_MINIMIZEBOX flags are there simply to make icon appear in taskbar
  2258. // WS_EX_TOOLWINDOW hides the taskbar/ALT-TAB button
  2259. DWORD style=0,style_ex=0;
  2260. if (!showTaskbarIcon)
  2261. {
  2262. style = WS_POPUP | WS_CLIPCHILDREN;
  2263. style_ex= WS_EX_TOOLWINDOW;
  2264. if (!hwndParent)
  2265. {
  2266. hwndParent = PLAT(_embeddedPanel)->hwnd;
  2267. }
  2268. }
  2269. else
  2270. {
  2271. style = WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPCHILDREN;
  2272. }
  2273. if (panel != _embeddedPanel && ((VPanel *)panel)->IsVisible())
  2274. {
  2275. style |= WS_VISIBLE;
  2276. }
  2277. if(disabled)
  2278. {
  2279. style |= WS_DISABLED;
  2280. }
  2281. if ( minimised )
  2282. {
  2283. style |= WS_MINIMIZE;
  2284. }
  2285. plat->hwnd = CreateWindowEx(style_ex, "Surface", "", style, x, y, wide, tall, hwndParent, NULL, GetModuleHandle(NULL), NULL);
  2286. plat->clipRgn = CreateRectRgn(0,0,64,64);
  2287. plat->hdc = CreateCompatibleDC(NULL);
  2288. plat->hwndDC = NULL;
  2289. plat->bitmap = 0;
  2290. plat->bitmapSize[0] = 0;
  2291. plat->bitmapSize[1] = 0;
  2292. plat->isFullscreen = false;
  2293. plat->embeddedPanel = (VPanel *)panel;
  2294. plat->disabled=disabled;
  2295. plat->notifyIcon = NULL;
  2296. plat->textureDC = NULL;
  2297. ::SetBkMode(plat->hdc, TRANSPARENT);
  2298. ::SetWindowLongPtr(plat->hwnd, GWLP_USERDATA, (LONG)g_pIVgui->PanelToHandle(panel));
  2299. ::SetTextAlign(plat->hdc, TA_LEFT | TA_TOP | TA_UPDATECP);
  2300. if (!((VPanel *)panel)->IsVisible() || panel == _embeddedPanel)
  2301. {
  2302. SetPanelVisible(panel, false);
  2303. }
  2304. // create the context
  2305. RecreateContext(panel);
  2306. ::RegisterDragDrop(plat->hwnd, &staticDragDropTarget);
  2307. // add the panel to the popup list
  2308. if (!_popupList.HasElement(panel))
  2309. {
  2310. _popupList.AddElement(panel);
  2311. }
  2312. else
  2313. {
  2314. // somehow getting added twice, fundamental problem
  2315. DebuggerBreak();
  2316. }
  2317. // hack, force a windows sound to be played
  2318. // the first time PlaySound is called there is 300ms hang, so this forces it to happen at startup
  2319. // instead of while the user is trying to do something
  2320. // we can't do this before a window created else it'll hang
  2321. static bool first = true;
  2322. if (first)
  2323. {
  2324. // double startTime = system()->GetCurrentTime();
  2325. ::PlaySoundA("", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT | SND_NOSTOP | SND_NOWAIT);
  2326. // double endTime = system()->GetCurrentTime();
  2327. // ivgui()->DPrintf2("PlaySound() : %dms\n", (int)((endTime - startTime) * 1000));
  2328. first = false;
  2329. }
  2330. //!! hack to set a valid current context panel
  2331. SetCurrentContextPanel(_embeddedPanel);
  2332. }
  2333. //-----------------------------------------------------------------------------
  2334. // Purpose: Called when a panel is created
  2335. //-----------------------------------------------------------------------------
  2336. void CWin32Surface::AddPanel(VPANEL panel)
  2337. {
  2338. }
  2339. //-----------------------------------------------------------------------------
  2340. // Purpose: Called when a panel gets deleted
  2341. //-----------------------------------------------------------------------------
  2342. void CWin32Surface::ReleasePanel(VPANEL panel)
  2343. {
  2344. _popupList.RemoveElement(panel);
  2345. if (panel == _currentContextPanel)
  2346. {
  2347. _currentContextPanel = _embeddedPanel;
  2348. }
  2349. if (PLAT(panel))
  2350. {
  2351. SurfacePlat *plat = PLAT(panel);
  2352. // release drag/drop
  2353. ::RevokeDragDrop(plat->hwnd);
  2354. // remove notify icons
  2355. if (plat->notifyIcon)
  2356. {
  2357. SetNotifyIcon(panel, NULL, NULL, NULL);
  2358. }
  2359. // hide the panel
  2360. SetPanelVisible(panel, false);
  2361. // free all the windows/bitmap/DC handles we are using
  2362. ::SetWindowLongPtr(plat->hwnd, GWLP_USERDATA, (LONG)-1);
  2363. ::SetWindowPos(plat->hwnd, HWND_BOTTOM, 0, 0, 1, 1, SWP_NOREDRAW|SWP_HIDEWINDOW);
  2364. // free the window context
  2365. if ( plat->bitmap )
  2366. {
  2367. ::DeleteObject( plat->bitmap );
  2368. }
  2369. if ( plat->textureDC )
  2370. {
  2371. ::DeleteDC( plat->textureDC );
  2372. }
  2373. if (plat->hwndDC)
  2374. {
  2375. ::ReleaseDC( plat->hwnd, plat->hwndDC );
  2376. }
  2377. ::DeleteDC( plat->hdc );
  2378. ::DestroyWindow( plat->hwnd );
  2379. ::DeleteObject( plat->clipRgn );
  2380. // don't free staticWndclassAtom, because it is shared amongst surfaces,
  2381. // and is automatically freed when the application terminates
  2382. delete plat;
  2383. ((VPanel *)panel)->SetPlat(NULL);
  2384. }
  2385. }
  2386. //-----------------------------------------------------------------------------
  2387. // Purpose: Applies any changes to the panel into the underline wnidow
  2388. //-----------------------------------------------------------------------------
  2389. bool CWin32Surface::RecreateContext(VPANEL panel)
  2390. {
  2391. if (panel && PLAT(panel))
  2392. {
  2393. SurfacePlat *plat = PLAT(panel);
  2394. int wide,tall;
  2395. ((VPanel *)panel)->GetSize(wide,tall);
  2396. // rebuild bitmap only if necessary
  2397. // simple scheme to prevent excessive allocations by allocating only when
  2398. // bigger. It also adds in 100 extra for subsequent sizings
  2399. // it will also realloc if the size is 200 smaller to shrink memory usage
  2400. if ((wide > plat->bitmapSize[0])
  2401. || (tall > plat->bitmapSize[1])
  2402. || (wide < (plat->bitmapSize[0] - 200))
  2403. || (tall < (plat->bitmapSize[1] - 200)))
  2404. {
  2405. if (plat->bitmap != 0)
  2406. {
  2407. ::DeleteObject(plat->bitmap);
  2408. }
  2409. plat->hwndDC = GetDC(plat->hwnd);
  2410. plat->bitmap = ::CreateCompatibleBitmap(plat->hwndDC, wide + 100, tall + 100);
  2411. plat->bitmapSize[0] = wide + 100;
  2412. plat->bitmapSize[1] = tall + 100;
  2413. if (plat->textureDC)
  2414. {
  2415. ::DeleteDC(plat->textureDC);
  2416. }
  2417. ::SelectObject(plat->hdc, plat->bitmap);
  2418. plat->textureDC = ::CreateCompatibleDC(plat->hdc);
  2419. ::ReleaseDC(plat->hwnd, plat->hwndDC);
  2420. plat->hwndDC = NULL;
  2421. }
  2422. }
  2423. return true;
  2424. }
  2425. //-----------------------------------------------------------------------------
  2426. // Purpose:
  2427. //-----------------------------------------------------------------------------
  2428. void CWin32Surface::EnableMouseCapture(VPANEL panel, bool state)
  2429. {
  2430. VPANEL contextPanel = GetContextPanelForChildPanel(panel);
  2431. if (state)
  2432. {
  2433. ::SetCapture(PLAT(contextPanel)->hwnd);
  2434. }
  2435. else
  2436. {
  2437. ::ReleaseCapture();
  2438. }
  2439. }
  2440. //-----------------------------------------------------------------------------
  2441. // Purpose:
  2442. //-----------------------------------------------------------------------------
  2443. bool CWin32Surface::ShouldPaintChildPanel(VPANEL childPanel)
  2444. {
  2445. // don't Paint children as part of the normal process, handle them in with WM_PAINT messages instead
  2446. return !((VPanel *)childPanel)->IsPopup();
  2447. }
  2448. //-----------------------------------------------------------------------------
  2449. // Purpose: Called after a Paint to display the new buffer
  2450. //-----------------------------------------------------------------------------
  2451. void CWin32Surface::SwapBuffers(VPANEL panel)
  2452. {
  2453. if (PLAT(panel))
  2454. {
  2455. START_TIMER();
  2456. SurfacePlat *plat = PLAT(panel);
  2457. int wide,tall;
  2458. ((VPanel *)panel)->GetSize(wide,tall);
  2459. plat->hwndDC = ::GetDC(plat->hwnd);
  2460. // reset origin and clipping then blit
  2461. ::SetRectRgn(plat->clipRgn, 0, 0, wide, tall);
  2462. ::SelectObject(plat->hdc, plat->clipRgn);
  2463. ::SetViewportOrgEx(plat->hdc, 0, 0, NULL);
  2464. ::BitBlt(plat->hwndDC, 0, 0, wide, tall, plat->hdc, 0, 0, SRCCOPY);
  2465. ::ReleaseDC(plat->hwnd, plat->hwndDC);
  2466. plat->hwndDC = NULL;
  2467. END_TIMER("SwapBuffers time: %.2fms\n");
  2468. }
  2469. }
  2470. //-----------------------------------------------------------------------------
  2471. // Purpose: Called every frame to change to window state if necessary
  2472. //-----------------------------------------------------------------------------
  2473. void CWin32Surface::ApplyChanges()
  2474. {
  2475. for (int i = 0; i < GetPopupCount(); i++)
  2476. {
  2477. VPANEL panel = GetPopup(i);
  2478. if (!PLAT(panel))
  2479. continue;
  2480. SurfacePlat *Plat = PLAT(panel);
  2481. // force the main panel to be invisible
  2482. if (panel == GetEmbeddedPanel())
  2483. {
  2484. ::ShowWindow(Plat->hwnd, SW_HIDE);
  2485. continue;
  2486. }
  2487. // hide and skip by invisible panels
  2488. if (!((VPanel *)panel)->IsVisible())
  2489. {
  2490. ::ShowWindow(Plat->hwnd, SW_HIDE);
  2491. continue;
  2492. }
  2493. RECT rect;
  2494. int x, y, wide, tall, sx, sy, swide, stall;
  2495. // get how big the win32 window
  2496. ::GetWindowRect(Plat->hwnd, &rect);
  2497. sx = rect.left;
  2498. sy = rect.top;
  2499. swide = rect.right-rect.left;
  2500. stall = rect.bottom-rect.top;
  2501. // how big is the embedded VPanel
  2502. ((VPanel *)panel)->GetPos(x, y);
  2503. ((VPanel *)panel)->GetSize(wide, tall);
  2504. // if they are not the same, then adjust the win32 window so it is
  2505. if ((x != sx) || (y != sy) || (wide != swide) || (tall != stall))
  2506. {
  2507. ::SetWindowPos(Plat->hwnd, 0, x, y, wide, tall, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
  2508. if ( sx > 0 || sy > 0 ) // only message for moves that are on the screen
  2509. {
  2510. g_pIVgui->PostMessage(panel, new KeyValues("Move"), NULL );
  2511. }
  2512. }
  2513. // check to see if the win32 window is visible
  2514. if (::GetWindowLong(Plat->hwnd, GWL_STYLE) & WS_VISIBLE)
  2515. {
  2516. //check to see if embedded VPanel is not visible, if so then hide the win32 window
  2517. if (!((VPanel *)panel)->IsVisible())
  2518. {
  2519. ::ShowWindow(Plat->hwnd, SW_HIDE);
  2520. }
  2521. }
  2522. else // win32 window is hidden
  2523. {
  2524. //check to see if embedded VPanel is visible, if so then show the win32 window
  2525. if (((VPanel *)panel)->IsVisible())
  2526. {
  2527. ::ShowWindow(Plat->hwnd, SW_SHOWNA);
  2528. }
  2529. }
  2530. //if the win32 window changed size and is visible, then the context needs to be recreated
  2531. if (((wide != swide) || (tall != stall)) && ((VPanel *)panel)->IsVisible())
  2532. {
  2533. RecreateContext(panel);
  2534. }
  2535. }
  2536. }
  2537. //-----------------------------------------------------------------------------
  2538. // Purpose: recurses the panels calculating absolute positions
  2539. // parents must be solved before children
  2540. //-----------------------------------------------------------------------------
  2541. void CWin32Surface::InternalSolveTraverse(VPANEL panel)
  2542. {
  2543. // solve the parent
  2544. ((VPanel *)panel)->Solve();
  2545. // now we can solve the children
  2546. for (int i = 0; i < ((VPanel *)panel)->GetChildCount(); i++)
  2547. {
  2548. VPanel *child = ((VPanel *)panel)->GetChild(i);
  2549. if (child->IsVisible())
  2550. {
  2551. InternalSolveTraverse((VPANEL)child);
  2552. }
  2553. }
  2554. }
  2555. //-----------------------------------------------------------------------------
  2556. // Purpose: recurses the panels giving them a chance to do a user-defined think,
  2557. // PerformLayout and ApplySchemeSettings
  2558. // must be done child before parent
  2559. //-----------------------------------------------------------------------------
  2560. void CWin32Surface::InternalThinkTraverse(VPANEL panel)
  2561. {
  2562. // parent
  2563. ((VPanel *)panel)->Client()->Think();
  2564. // then the children...
  2565. for (int i = 0; i < ((VPanel *)panel)->GetChildCount(); i++)
  2566. {
  2567. VPanel *child = ((VPanel *)panel)->GetChild(i);
  2568. if (child->IsVisible())
  2569. {
  2570. InternalThinkTraverse((VPANEL)child);
  2571. }
  2572. }
  2573. }
  2574. //-----------------------------------------------------------------------------
  2575. // Purpose: recurses the panels giving them a chance to do a ApplySchemeSettings
  2576. // must be done child before parent
  2577. //-----------------------------------------------------------------------------
  2578. void CWin32Surface::InternalSchemeSettingsTraverse(VPANEL panel, bool forceApplySchemeSettings)
  2579. {
  2580. // think the children...
  2581. for (int i = 0; i < ((VPanel *)panel)->GetChildCount(); i++)
  2582. {
  2583. VPanel *child = ((VPanel *)panel)->GetChild(i);
  2584. if ( forceApplySchemeSettings || child->IsVisible() )
  2585. {
  2586. InternalSchemeSettingsTraverse((VPANEL)child, forceApplySchemeSettings);
  2587. }
  2588. }
  2589. // ... then the parent
  2590. ((VPanel *)panel)->Client()->PerformApplySchemeSettings();
  2591. }
  2592. //-----------------------------------------------------------------------------
  2593. // Purpose: Walks through the panel tree calling Solve() on them all, in order
  2594. //-----------------------------------------------------------------------------
  2595. void CWin32Surface::SolveTraverse(VPANEL panel, bool forceApplySchemeSettings)
  2596. {
  2597. // ignore visibility for this
  2598. InternalSchemeSettingsTraverse(panel,forceApplySchemeSettings); // do apply scheme settings, child to parent
  2599. if (!((VPanel *)panel)->IsVisible())
  2600. return;
  2601. InternalThinkTraverse(panel);
  2602. InternalSolveTraverse(panel);
  2603. }
  2604. //-----------------------------------------------------------------------------
  2605. // Purpose:
  2606. //-----------------------------------------------------------------------------
  2607. void CWin32Surface::PaintTraverse(VPANEL panel)
  2608. {
  2609. START_TIMER();
  2610. ((VPanel *)panel)->Client()->PaintTraverse(false,true);
  2611. END_TIMER("Paint time: %.2fms\n");
  2612. }
  2613. // FIXME: write these functions!
  2614. void CWin32Surface::RestrictPaintToSinglePanel( VPANEL panel, bool bForceAllowNonModalSurface )
  2615. {
  2616. }
  2617. void CWin32Surface::SetModalPanel(VPANEL )
  2618. {
  2619. }
  2620. VPANEL CWin32Surface::GetModalPanel()
  2621. {
  2622. return 0;
  2623. }
  2624. void CWin32Surface::UnlockCursor()
  2625. {
  2626. }
  2627. void CWin32Surface::LockCursor()
  2628. {
  2629. }
  2630. void CWin32Surface::SetTranslateExtendedKeys(bool state)
  2631. {
  2632. }
  2633. VPANEL CWin32Surface::GetTopmostPopup()
  2634. {
  2635. return 0;
  2636. }
  2637. //-----------------------------------------------------------------------------
  2638. // Purpose: Checks to see if the mouse should be visible or not
  2639. //-----------------------------------------------------------------------------
  2640. void CWin32Surface::CalculateMouseVisible()
  2641. {
  2642. int i;
  2643. _needMouse = false;
  2644. _needKB = false;
  2645. for(i = 0 ; i < g_pSurface->GetPopupCount() ; i++ )
  2646. {
  2647. VPanel *pop = (VPanel *)g_pSurface->GetPopup( i ) ;
  2648. bool isVisible=pop->IsVisible();
  2649. VPanel *p= pop->GetParent();
  2650. while(p && isVisible)
  2651. {
  2652. if( p->IsVisible()==false)
  2653. {
  2654. isVisible=false;
  2655. break;
  2656. }
  2657. p=p->GetParent();
  2658. }
  2659. if(isVisible)
  2660. {
  2661. _needMouse |= pop->IsMouseInputEnabled();
  2662. _needKB |= pop->IsKeyBoardInputEnabled();
  2663. }
  2664. }
  2665. if (_needMouse)
  2666. {
  2667. SetCursor(vgui::dc_arrow);
  2668. UnlockCursor();
  2669. }
  2670. }
  2671. //-----------------------------------------------------------------------------
  2672. // Purpose:
  2673. //-----------------------------------------------------------------------------
  2674. bool CWin32Surface::NeedKBInput()
  2675. {
  2676. return _needKB;
  2677. }
  2678. //-----------------------------------------------------------------------------
  2679. // Purpose: Sets the current cursor
  2680. //-----------------------------------------------------------------------------
  2681. void CWin32Surface::SetCursor(HCursor cursor)
  2682. {
  2683. switch (cursor)
  2684. {
  2685. case dc_none:
  2686. case dc_arrow:
  2687. case dc_ibeam:
  2688. case dc_hourglass:
  2689. case dc_waitarrow:
  2690. case dc_crosshair:
  2691. case dc_up:
  2692. case dc_sizenwse:
  2693. case dc_sizenesw:
  2694. case dc_sizewe:
  2695. case dc_sizens:
  2696. case dc_sizeall:
  2697. case dc_no:
  2698. case dc_hand:
  2699. {
  2700. _currentCursor = staticDefaultCursor[cursor];
  2701. break;
  2702. }
  2703. case dc_user:
  2704. {
  2705. break;
  2706. }
  2707. case dc_blank: // don't touch the cursor, just stick with what windows is currently using
  2708. {
  2709. return;
  2710. break;
  2711. }
  2712. }
  2713. ::SetCursor(_currentCursor);
  2714. }
  2715. //-----------------------------------------------------------------------------
  2716. // Purpose: Forces the window to be redrawn
  2717. //-----------------------------------------------------------------------------
  2718. void CWin32Surface::Invalidate(VPANEL panel)
  2719. {
  2720. panel = GetContextPanelForChildPanel(panel);
  2721. if (panel && PLAT(panel) && ((VPanel *)panel)->IsVisible())
  2722. {
  2723. // last parm must be false so WM_ERASEBKGND is not generated, that should
  2724. // only be generated by windows
  2725. InvalidateRect(PLAT(panel)->hwnd, NULL, false);
  2726. }
  2727. }
  2728. //-----------------------------------------------------------------------------
  2729. // Purpose: Checks to see if any of the windows have focus
  2730. // Output : Returns true on success, false on failure.
  2731. //-----------------------------------------------------------------------------
  2732. bool CWin32Surface::HasFocus()
  2733. {
  2734. HWND focus = ::GetFocus();
  2735. if (!focus)
  2736. return false;
  2737. // see if any of the windows on the surface have the focus
  2738. for (int i = 0; i < GetPopupCount(); i++)
  2739. {
  2740. VPANEL panel = GetPopup(i);
  2741. if (focus == PLAT(panel)->hwnd)
  2742. return true;
  2743. }
  2744. return false;
  2745. }
  2746. //-----------------------------------------------------------------------------
  2747. // Purpose: Returns true if the cursor is over this surface
  2748. // Uses the windows call to do this, instead of doing it procedurally
  2749. //-----------------------------------------------------------------------------
  2750. bool CWin32Surface::IsWithin(int x,int y)
  2751. {
  2752. POINT pnt={x,y};
  2753. HWND hwnd = WindowFromPoint(pnt);
  2754. for (int i = 0; i < GetPopupCount(); i++)
  2755. {
  2756. if (PLAT(GetPopup(i))->hwnd == hwnd)
  2757. {
  2758. return true;
  2759. }
  2760. }
  2761. return false;
  2762. }
  2763. //-----------------------------------------------------------------------------
  2764. // Purpose: handles a set focus message
  2765. //-----------------------------------------------------------------------------
  2766. void CWin32Surface::setFocus(VPANEL panel)
  2767. {
  2768. // reset the focus to the last focused panel
  2769. panel = GetContextPanelForChildPanel(panel);
  2770. if (panel && PLAT(panel))
  2771. {
  2772. // make sure we have a valid panel
  2773. VPANEL focus = panel;
  2774. if (focus && ((VPanel *)focus)->HasParent((VPanel *)panel))
  2775. {
  2776. // Must be a child of the modal surface, if set
  2777. if ( g_pInput->GetAppModalSurface() && !((VPanel *)focus)->HasParent((VPanel *)g_pInput->GetAppModalSurface()) )
  2778. {
  2779. // trying to set focus to something that's not the modal panel, set it back
  2780. SetForegroundWindow(g_pInput->GetAppModalSurface());
  2781. }
  2782. else
  2783. {
  2784. // make sure focus is at top of list
  2785. // the subfocus will be automatically calculated in IInput::RunFrame()
  2786. ((VPanel *)focus)->MoveToFront();
  2787. return;
  2788. }
  2789. }
  2790. }
  2791. // let the main panel get focus as the default
  2792. if (panel)
  2793. {
  2794. ((VPanel *)panel)->Client()->RequestFocus(0);
  2795. }
  2796. }
  2797. struct FontRangeItem_t
  2798. {
  2799. const char *name;
  2800. int lowerRange;
  2801. int upperRange;
  2802. };
  2803. FontRangeItem_t g_FontRanges[] =
  2804. {
  2805. { "Basic Latin", 0x0000, 0x007F },
  2806. { "Latin-1 Supplement", 0x0080, 0x00FF },
  2807. { "Latin Extended-A", 0x0100, 0x017F },
  2808. { "Latin Extended-B", 0x0180, 0x024F },
  2809. { "IPA Extensions", 0x0250, 0x02AF },
  2810. { "Spacing Modifier Letters", 0x02B0, 0x02FF },
  2811. { "Combining Diacritical Marks", 0x0300, 0x036F },
  2812. { "Greek", 0x0370, 0x03FF },
  2813. { "Cyrillic", 0x0400, 0x04FF },
  2814. { "Armenian", 0x0530, 0x058F },
  2815. { "Hebrew", 0x0590, 0x05FF },
  2816. { "Arabic", 0x0600, 0x06FF },
  2817. { "Syriac", 0x0700, 0x074F },
  2818. { "Thaana", 0x0780, 0x07BF },
  2819. { "Devanagari", 0x0900, 0x097F },
  2820. { "Bengali", 0x0980, 0x09FF },
  2821. { "Gurmukhi", 0x0A00, 0x0A7F },
  2822. { "Gujarati", 0x0A80, 0x0AFF },
  2823. { "Oriya", 0x0B00, 0x0B7F },
  2824. { "Tamil", 0x0B80, 0x0BFF },
  2825. { "Telugu", 0x0C00, 0x0C7F },
  2826. { "Kannada", 0x0C80, 0x0CFF },
  2827. { "Malayalam", 0x0D00, 0x0D7F },
  2828. { "Sinhala", 0x0D80, 0x0DFF },
  2829. { "Thai", 0x0E00, 0x0E7F },
  2830. { "Lao", 0x0E80, 0x0EFF },
  2831. { "Tibetan", 0x0F00, 0x0FBF },
  2832. { "Myanmar", 0x1000, 0x109F },
  2833. { "Georgian", 0x10A0, 0x10FF },
  2834. { "Hangul Jamo", 0x1100, 0x11FF },
  2835. { "Ethiopic", 0x1200, 0x137F },
  2836. { "Cherokee", 0x13A0, 0x13FF },
  2837. { "Unified Canadian Aboriginal Syllabics", 0x1400, 0x167F },
  2838. { "Ogham", 0x1680, 0x169F },
  2839. { "Runic", 0x16A0, 0x16FF },
  2840. { "Khmer", 0x1780, 0x17FF },
  2841. { "Mongolian", 0x1800, 0x18AF },
  2842. { "Latin Extended Additional", 0x1E00, 0x1EFF },
  2843. { "Greek Extended", 0x1F00, 0x1FFF },
  2844. { "General Punctuation", 0x2000, 0x206F },
  2845. { "Superscripts and Subscripts", 0x2070, 0x209F },
  2846. { "Currency Symbols", 0x20A0, 0x20CF },
  2847. { "Combining Diacritical Marks for Symbols",0x20D0, 0x20FF },
  2848. { "Letterlike Symbols", 0x2100, 0x214F },
  2849. { "Number Forms", 0x2150, 0x218F },
  2850. { "Arrows", 0x2190, 0x21FF },
  2851. { "Mathematical Operators", 0x2200, 0x22FF },
  2852. { "Miscellaneous Technical", 0x2300, 0x23FF },
  2853. { "Control Pictures", 0x2400, 0x243F },
  2854. { "Optical Character Recognition", 0x2440, 0x245F },
  2855. { "Enclosed Alphanumerics", 0x2460, 0x24FF },
  2856. { "Box Drawing", 0x2500, 0x257F },
  2857. { "Block Elements", 0x2580, 0x259F },
  2858. { "Geometric Shapes", 0x25A0, 0x25FF },
  2859. { "Miscellaneous Symbols", 0x2600, 0x26FF },
  2860. { "Dingbats", 0x2700, 0x27BF },
  2861. { "Braille Patterns", 0x2800, 0x28FF },
  2862. { "CJK Radicals Supplement", 0x2E80, 0x2EFF },
  2863. { "KangXi Radicals", 0x2F00, 0x2FDF },
  2864. { "Ideographic Description Characters", 0x2FF0, 0x2FFF },
  2865. { "CJK Symbols and Punctuation", 0x3000, 0x303F },
  2866. { "Hiragana", 0x3040, 0x309F },
  2867. { "Katakana", 0x30A0, 0x30FF },
  2868. { "Bopomofo", 0x3100, 0x312F },
  2869. { "Hangul Compatibility Jamo", 0x3130, 0x318F },
  2870. { "Kanbun", 0x3190, 0x319F },
  2871. { "Bopomofo Extended", 0x31A0, 0x31BF },
  2872. { "Enclosed CJK Letters and Months", 0x3200, 0x32FF },
  2873. { "CJK Compatibility", 0x3300, 0x33FF },
  2874. { "CJK Unified Ideographs Extension A", 0x3400, 0x4DB5 },
  2875. { "CJK Unified Ideographs", 0x4E00, 0x9FFF },
  2876. { "Yi Syllables", 0xA000, 0xA48F },
  2877. { "Yi Radicals", 0xA490, 0xA4CF },
  2878. { "Hangul Syllables", 0xAC00, 0xD7A3 },
  2879. { "-- surrogates --", 0xD800, 0xDBFF },
  2880. { "CJK Compatibility Ideographs", 0xF900, 0xFAFF },
  2881. { "Alphabetic Presentation Forms", 0xFB00, 0xFB4F },
  2882. { "Arabic Presentation Forms-A", 0xFB50, 0xFDFF },
  2883. { "Combining Half Marks", 0xFE20, 0xFE2F },
  2884. { "CJK Compatibility Forms", 0xFE30, 0xFE4F },
  2885. { "Small Form Variants", 0xFE50, 0xFE6F },
  2886. { "Arabic Presentation Forms-B", 0xFE70, 0xFEFF },
  2887. { "Halfwidth and Fullwidth Forms", 0xFF00, 0xFFEF },
  2888. { "Specials", 0xFFF0, 0xFFFF },
  2889. };
  2890. //-----------------------------------------------------------------------------
  2891. // Purpose: creates a new empty font
  2892. //-----------------------------------------------------------------------------
  2893. HFont CWin32Surface::CreateFont()
  2894. {
  2895. return FontManager().CreateFont();
  2896. }
  2897. //-----------------------------------------------------------------------------
  2898. // Purpose: adds glyphs to a font created by CreateFont()
  2899. //-----------------------------------------------------------------------------
  2900. bool CWin32Surface::SetFontGlyphSet(HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int nRangeMin, int nRangeMax)
  2901. {
  2902. return FontManager().SetFontGlyphSet(font, windowsFontName, tall, weight, blur, scanlines, flags, nRangeMin, nRangeMax);
  2903. }
  2904. //-----------------------------------------------------------------------------
  2905. // Purpose: returns the max height of a font
  2906. //-----------------------------------------------------------------------------
  2907. int CWin32Surface::GetFontTall(HFont font)
  2908. {
  2909. return FontManager().GetFontTall(font);
  2910. }
  2911. //-----------------------------------------------------------------------------
  2912. // Purpose: returns the max height of a font
  2913. //-----------------------------------------------------------------------------
  2914. int CWin32Surface::GetFontAscent(HFont font, wchar_t wch)
  2915. {
  2916. return FontManager().GetFontAscent(font,wch);
  2917. }
  2918. //-----------------------------------------------------------------------------
  2919. // Purpose:
  2920. // Input : font -
  2921. // Output : Returns true on success, false on failure.
  2922. //-----------------------------------------------------------------------------
  2923. bool CWin32Surface::IsFontAdditive(HFont font)
  2924. {
  2925. return FontManager().IsFontAdditive(font);
  2926. }
  2927. //-----------------------------------------------------------------------------
  2928. // Purpose: returns the abc widths of a single character
  2929. //-----------------------------------------------------------------------------
  2930. void CWin32Surface::GetCharABCwide(HFont font, int ch, int &a, int &b, int &c)
  2931. {
  2932. FontManager().GetCharABCwide(font, ch, a, b, c);
  2933. }
  2934. //-----------------------------------------------------------------------------
  2935. // Purpose: returns the pixel width of a single character
  2936. //-----------------------------------------------------------------------------
  2937. int CWin32Surface::GetCharacterWidth(HFont font, int ch)
  2938. {
  2939. return FontManager().GetCharacterWidth(font, ch);
  2940. }
  2941. //-----------------------------------------------------------------------------
  2942. // Purpose: returns the area of a text string, including newlines
  2943. //-----------------------------------------------------------------------------
  2944. void CWin32Surface::GetTextSize(HFont font, const wchar_t *text, int &wide, int &tall)
  2945. {
  2946. FontManager().GetTextSize(font, text, wide, tall);
  2947. }
  2948. //-----------------------------------------------------------------------------
  2949. // Used by the localization library
  2950. //-----------------------------------------------------------------------------
  2951. int CWin32Surface::ComputeTextWidth( const wchar_t *pString )
  2952. {
  2953. int nWide, nTall;
  2954. GetTextSize( 1, pString, nWide, nTall );
  2955. return nWide;
  2956. }
  2957. //-----------------------------------------------------------------------------
  2958. // Purpose: adds a custom font file
  2959. // load the .vfont file
  2960. //-----------------------------------------------------------------------------
  2961. bool CWin32Surface::AddCustomFontFile(const char *fontFileName)
  2962. {
  2963. #ifdef SUPPORT_CUSTOM_FONT_FORMAT
  2964. CUtlBuffer buf;
  2965. if ( !g_pFullFileSystem->ReadFile( fontFileName, NULL, buf ) )
  2966. return false;
  2967. if ( !ValveFont::DecodeFont( buf ) )
  2968. return false;
  2969. DWORD dwNumFontsRegistered = 0;
  2970. HANDLE hRegistered = NULL;
  2971. hRegistered = ::AddFontMemResourceEx( buf.Base(), buf.TellPut(), NULL, &dwNumFontsRegistered );
  2972. return hRegistered != NULL;
  2973. #else
  2974. char fullPath[ MAX_PATH ];
  2975. g_pFullFileSystem->GetLocalPath(fontFileName, fullPath, sizeof( fullPath ));
  2976. m_CustomFontFileNames.AddToTail(fontFileName);
  2977. return (::AddFontResource(fullPath) > 0);
  2978. #endif
  2979. }
  2980. //-----------------------------------------------------------------------------
  2981. // Purpose: Pre-compiled bitmap font support for game engine - not implemented for GDI
  2982. //-----------------------------------------------------------------------------
  2983. bool CWin32Surface::AddBitmapFontFile(const char *fontFileName)
  2984. {
  2985. Assert( 0 );
  2986. return false;
  2987. }
  2988. void CWin32Surface::SetBitmapFontName( const char *pName, const char *pFontFilename )
  2989. {
  2990. Assert( 0 );
  2991. }
  2992. const char *CWin32Surface::GetBitmapFontName( const char *pName )
  2993. {
  2994. Assert( 0 );
  2995. return NULL;
  2996. }
  2997. bool CWin32Surface::SetBitmapFontGlyphSet(HFont font, const char *windowsFontName, float scalex, float scaley, int flags)
  2998. {
  2999. Assert( 0 );
  3000. return false;
  3001. }
  3002. void CWin32Surface::PrecacheFontCharacters(HFont font, wchar_t *pCharacters)
  3003. {
  3004. Assert( 0 );
  3005. }
  3006. void CWin32Surface::ClearTemporaryFontCache( void )
  3007. {
  3008. Assert( 0 );
  3009. }
  3010. const char *CWin32Surface::GetFontName( HFont font )
  3011. {
  3012. return FontManager().GetFontName( font );
  3013. }
  3014. void CWin32Surface::DrawSetTextScale(float sx, float sy)
  3015. {
  3016. Assert( 0 );
  3017. }
  3018. void CWin32Surface::SetPanelForInput( VPANEL vpanel )
  3019. {
  3020. Assert( 0 );
  3021. }
  3022. void CWin32Surface::DrawFilledRectFastFade( int x0, int y0, int x1, int y1, int fadeStartPt, int fadeEndPt, unsigned int alpha0, unsigned int alpha1, bool bHorizontal )
  3023. {
  3024. Assert( 0 );
  3025. }
  3026. void CWin32Surface::DrawFilledRectFade( int x0, int y0, int x1, int y1, unsigned int alpha0, unsigned int alpha1, bool bHorizontal )
  3027. {
  3028. Assert( 0 );
  3029. }
  3030. //-----------------------------------------------------------------------------
  3031. // Purpose: Returns the bounds of the usable workspace area
  3032. //-----------------------------------------------------------------------------
  3033. void CWin32Surface::GetWorkspaceBounds(int &x, int &y, int &wide, int &tall)
  3034. {
  3035. RECT rcScreen;
  3036. ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, 0);
  3037. x = rcScreen.left;
  3038. y = rcScreen.top;
  3039. wide = rcScreen.right - x;
  3040. tall = rcScreen.bottom - y;
  3041. }
  3042. //-----------------------------------------------------------------------------
  3043. // Purpose: gets the absolute coordinates of the screen (in screen space)
  3044. //-----------------------------------------------------------------------------
  3045. void CWin32Surface::GetAbsoluteWindowBounds(int &x, int &y, int &wide, int &tall)
  3046. {
  3047. // always work in full window screen space
  3048. x = 0;
  3049. y = 0;
  3050. GetScreenSize(wide, tall);
  3051. }
  3052. //-----------------------------------------------------------------------------
  3053. // Purpose: Plays a sound
  3054. // Input : *fileName - name of the wav file
  3055. //-----------------------------------------------------------------------------
  3056. void CWin32Surface::PlaySound(const char *fileName)
  3057. {
  3058. char localPath[MAX_PATH];
  3059. if (!g_pFullFileSystem->GetLocalPath(fileName, localPath, sizeof(localPath)))
  3060. return;
  3061. g_pFullFileSystem->GetLocalCopy(localPath);
  3062. ::PlaySoundA(localPath, NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT | SND_NOSTOP | SND_NOWAIT);
  3063. }
  3064. void CWin32Surface::SetAbsPosForContext( int id, int x, int y )
  3065. {
  3066. ContextAbsPos_t search;
  3067. search.id = id;
  3068. int idx = m_ContextAbsPos.Find( search );
  3069. if ( idx == m_ContextAbsPos.InvalidIndex() )
  3070. {
  3071. idx = m_ContextAbsPos.Insert( search );
  3072. }
  3073. ContextAbsPos_t &entry = m_ContextAbsPos[ idx ];
  3074. entry.m_nPos[ 0 ] = x;
  3075. entry.m_nPos[ 1 ] = y;
  3076. }
  3077. void CWin32Surface::GetAbsPosForContext( int id, int &x, int& y )
  3078. {
  3079. ContextAbsPos_t search;
  3080. search.id = id;
  3081. int idx = m_ContextAbsPos.Find( search );
  3082. if ( idx == m_ContextAbsPos.InvalidIndex() )
  3083. {
  3084. x = y = 0;
  3085. return;
  3086. }
  3087. const ContextAbsPos_t &entry = m_ContextAbsPos[ idx ];
  3088. x = entry.m_nPos[ 0 ];
  3089. y = entry.m_nPos[ 1 ];
  3090. }
  3091. bool GetIconSize( ICONINFO& iconInfo, int& w, int& h )
  3092. {
  3093. w = h = 0;
  3094. HBITMAP bitmap = iconInfo.hbmColor;
  3095. BITMAP bm;
  3096. if ( 0 == GetObject((HGDIOBJ)bitmap, sizeof(BITMAP), (LPVOID)&bm) )
  3097. {
  3098. return false;
  3099. }
  3100. w = bm.bmWidth;
  3101. h = bm.bmHeight;
  3102. return true;
  3103. }
  3104. class CIconImage : public IImage
  3105. {
  3106. public:
  3107. CIconImage( HICON hIcon ) : m_hIcon( CopyIcon( hIcon ) )
  3108. {
  3109. m_Pos.x = m_Pos.y = 0;
  3110. ICONINFO iconInfo;
  3111. if ( 0 != GetIconInfo( m_hIcon, &iconInfo ) )
  3112. {
  3113. int w, h;
  3114. GetIconSize( iconInfo, w, h );
  3115. m_Size.cx = w;
  3116. m_Size.cy = h;
  3117. }
  3118. else
  3119. {
  3120. m_Size.cx = 0;
  3121. m_Size.cy = 0;
  3122. }
  3123. }
  3124. // virtual destructor
  3125. virtual ~CIconImage()
  3126. {
  3127. DestroyIcon( m_hIcon );
  3128. }
  3129. // Call to Paint the image
  3130. // Image will draw within the current panel context at the specified position
  3131. virtual void Paint()
  3132. {
  3133. if ( !m_hIcon )
  3134. return;
  3135. if ( !m_Size.cx || !m_Size.cy )
  3136. return;
  3137. HDC hdc = PLAT(g_Surface._currentContextPanel)->hdc;
  3138. // Translate position to screen space based on surface state...
  3139. int x, y;
  3140. x = m_Pos.x;
  3141. y = m_Pos.y;
  3142. DrawIconEx
  3143. (
  3144. hdc,
  3145. x, y,
  3146. m_hIcon,
  3147. m_Size.cx, m_Size.cy,
  3148. 0,
  3149. NULL,
  3150. DI_NORMAL
  3151. );
  3152. }
  3153. // Set the position of the image
  3154. virtual void SetPos(int x, int y)
  3155. {
  3156. m_Pos.x = x;
  3157. m_Pos.y = y;
  3158. }
  3159. // Gets the size of the content
  3160. virtual void GetContentSize(int &wide, int &tall)
  3161. {
  3162. wide = m_Size.cx;
  3163. tall = m_Size.cy;
  3164. }
  3165. // Get the size the image will actually draw in (usually defaults to the content size)
  3166. virtual void GetSize(int &wide, int &tall)
  3167. {
  3168. GetContentSize( wide, tall );
  3169. }
  3170. // Sets the size of the image
  3171. virtual void SetSize(int wide, int tall)
  3172. {
  3173. // Nothing
  3174. }
  3175. // Set the draw color
  3176. virtual void SetColor(Color col)
  3177. {
  3178. // Nothing
  3179. }
  3180. virtual bool Evict() { return false; }
  3181. virtual int GetNumFrames() { return 0; }
  3182. virtual void SetFrame( int nFrame ) {}
  3183. virtual HTexture GetID() { return 0; }
  3184. virtual void SetRotation( int iRotation ) { return; };
  3185. private:
  3186. HICON m_hIcon;
  3187. POINT m_Pos;
  3188. SIZE m_Size;
  3189. };
  3190. static char const *g_pUniqueExtensions[]=
  3191. {
  3192. "exe",
  3193. "cur",
  3194. "ani",
  3195. };
  3196. static bool ShouldMakeUnique( char const *extension )
  3197. {
  3198. for ( int i = 0; i < ARRAYSIZE( g_pUniqueExtensions ); ++i )
  3199. {
  3200. if ( !Q_stricmp( extension, g_pUniqueExtensions[ i ] ) )
  3201. return true;
  3202. }
  3203. return false;
  3204. }
  3205. IImage *CWin32Surface::GetIconImageForFullPath( char const *pFullPath )
  3206. {
  3207. IImage *newIcon = NULL;
  3208. SHFILEINFO info = { 0 };
  3209. DWORD_PTR dwResult = SHGetFileInfo(
  3210. pFullPath,
  3211. 0,
  3212. &info,
  3213. sizeof( info ),
  3214. SHGFI_TYPENAME | SHGFI_ICON | SHGFI_SMALLICON | SHGFI_SHELLICONSIZE
  3215. );
  3216. if ( dwResult )
  3217. {
  3218. if ( info.szTypeName[ 0 ] != 0 )
  3219. {
  3220. char ext[ 32 ];
  3221. Q_ExtractFileExtension( pFullPath, ext, sizeof( ext ) );
  3222. char lookup[ 512 ];
  3223. Q_snprintf( lookup, sizeof( lookup ), "%s", ShouldMakeUnique( ext ) ? pFullPath : info.szTypeName );
  3224. // Now check the dictionary
  3225. unsigned short idx = m_FileTypeImages.Find( lookup );
  3226. if ( idx == m_FileTypeImages.InvalidIndex() )
  3227. {
  3228. newIcon = new CIconImage( info.hIcon );
  3229. idx = m_FileTypeImages.Insert( lookup, newIcon );
  3230. }
  3231. newIcon = m_FileTypeImages[ idx ];
  3232. }
  3233. DestroyIcon( info.hIcon );
  3234. }
  3235. return newIcon;
  3236. }
  3237. //-----------------------------------------------------------------------------
  3238. // Purpose: Handles windows message pump
  3239. //-----------------------------------------------------------------------------
  3240. void CWin32Surface::RunFrame()
  3241. {
  3242. ::MSG msg;
  3243. if (!g_pIVgui->GetShouldVGuiControlSleep())
  3244. {
  3245. // if vgui doesn't control sleeping, then make sure we don't block in this loop
  3246. if (!::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
  3247. return;
  3248. }
  3249. // always get at least one message
  3250. // this means it will block until input
  3251. // there is a timer set to force this loop to run at least 20Hz, which should be fine for the desktop
  3252. do
  3253. {
  3254. BOOL ret = ::GetMessage(&msg, NULL, 0, 0);
  3255. if (ret == 0)
  3256. break;
  3257. if (ret == -1)
  3258. {
  3259. g_pIVgui->Stop();
  3260. break;
  3261. }
  3262. ::TranslateMessage(&msg);
  3263. ::DispatchMessage(&msg);
  3264. }
  3265. while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE));
  3266. }
  3267. //-----------------------------------------------------------------------------
  3268. // Purpose: cap bits
  3269. //-----------------------------------------------------------------------------
  3270. bool CWin32Surface::SupportsFontFeature( FontFeature_t feature )
  3271. {
  3272. switch ( feature )
  3273. {
  3274. case FONT_FEATURE_ANTIALIASED_FONTS:
  3275. return true;
  3276. case FONT_FEATURE_DROPSHADOW_FONTS:
  3277. case FONT_FEATURE_OUTLINE_FONTS:
  3278. default:
  3279. return false;
  3280. };
  3281. }
  3282. //-----------------------------------------------------------------------------
  3283. // Purpose: cap bits
  3284. //-----------------------------------------------------------------------------
  3285. bool CWin32Surface::SupportsFeature( SurfaceFeature_t feature )
  3286. {
  3287. switch ( feature )
  3288. {
  3289. case ISurface::ESCAPE_KEY:
  3290. case ISurface::OPENING_NEW_HTML_WINDOWS:
  3291. case ISurface::FRAME_MINIMIZE_MAXIMIZE:
  3292. case ISurface::DIRECT_HWND_RENDER:
  3293. return true;
  3294. case ISurface::ANTIALIASED_FONTS:
  3295. case ISurface::DROPSHADOW_FONTS:
  3296. case ISurface::OUTLINE_FONTS:
  3297. return SupportsFontFeature( ( FontFeature_t )feature );
  3298. default:
  3299. return false;
  3300. };
  3301. }
  3302. //-----------------------------------------------------------------------------
  3303. // Purpose: Initializes all the static data for the app
  3304. // Should be only called during load time
  3305. //-----------------------------------------------------------------------------
  3306. void CWin32Surface::initStaticData()
  3307. {
  3308. //load up all default cursors, this gets called everytime a Surface is created, but
  3309. //who cares
  3310. staticDefaultCursor[dc_none] =0;
  3311. staticDefaultCursor[dc_arrow] =(HICON)LoadCursor(0,(LPCTSTR)OCR_NORMAL);
  3312. staticDefaultCursor[dc_ibeam] =(HICON)LoadCursor(0,(LPCTSTR)OCR_IBEAM);
  3313. staticDefaultCursor[dc_hourglass]=(HICON)LoadCursor(0,(LPCTSTR)OCR_WAIT);
  3314. staticDefaultCursor[dc_waitarrow]=(HICON)LoadCursor(0,(LPCTSTR)OCR_APPSTARTING);
  3315. staticDefaultCursor[dc_crosshair]=(HICON)LoadCursor(0,(LPCTSTR)OCR_CROSS);
  3316. staticDefaultCursor[dc_up] =(HICON)LoadCursor(0,(LPCTSTR)OCR_UP);
  3317. staticDefaultCursor[dc_sizenwse] =(HICON)LoadCursor(0,(LPCTSTR)OCR_SIZENWSE);
  3318. staticDefaultCursor[dc_sizenesw] =(HICON)LoadCursor(0,(LPCTSTR)OCR_SIZENESW);
  3319. staticDefaultCursor[dc_sizewe] =(HICON)LoadCursor(0,(LPCTSTR)OCR_SIZEWE);
  3320. staticDefaultCursor[dc_sizens] =(HICON)LoadCursor(0,(LPCTSTR)OCR_SIZENS);
  3321. staticDefaultCursor[dc_sizeall] =(HICON)LoadCursor(0,(LPCTSTR)OCR_SIZEALL);
  3322. staticDefaultCursor[dc_no] =(HICON)LoadCursor(0,(LPCTSTR)OCR_NO);
  3323. staticDefaultCursor[dc_hand] =(HICON)LoadCursor(0,(LPCTSTR)32649);
  3324. // make and register a very simple Window Class
  3325. memset( &staticWndclass,0,sizeof(staticWndclass) );
  3326. staticWndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  3327. staticWndclass.lpfnWndProc = staticProc;
  3328. staticWndclass.hInstance = GetModuleHandle(NULL);
  3329. // Get the resource ID of the icon group from the environment...default to 101.
  3330. DWORD wIconID = 101;
  3331. const char *sIconResourceID = getenv(szSteamBootStrapperIconIdEnvVar);
  3332. if ( sIconResourceID )
  3333. {
  3334. DWORD wTmpIconID = 0;
  3335. if ( sscanf(sIconResourceID, "%u", &wTmpIconID) == 1 && wTmpIconID > 101 )
  3336. {
  3337. wIconID = wTmpIconID;
  3338. }
  3339. }
  3340. staticWndclass.hIcon = ::LoadIcon(staticWndclass.hInstance, MAKEINTRESOURCE(wIconID));
  3341. staticWndclass.lpszClassName = "Surface";
  3342. staticWndclassAtom = ::RegisterClass( &staticWndclass );
  3343. // register our global Shutdown command
  3344. staticShutdownMsg = ::RegisterWindowMessage("ShutdownValvePlatform");
  3345. }
  3346. //-----------------------------------------------------------------------------
  3347. //
  3348. //-----------------------------------------------------------------------------
  3349. void CWin32Surface::SetLanguage( const char *pLanguage )
  3350. {
  3351. FontManager().SetLanguage( pLanguage );
  3352. }
  3353. //-----------------------------------------------------------------------------
  3354. //
  3355. //-----------------------------------------------------------------------------
  3356. const char *CWin32Surface::GetLanguage()
  3357. {
  3358. return FontManager().GetLanguage();
  3359. }
  3360. //-----------------------------------------------------------------------------
  3361. // Purpose: our basic user agent string when doing http requests from the client for webkit
  3362. //-----------------------------------------------------------------------------
  3363. const char *CWin32Surface::GetWebkitHTMLUserAgentString()
  3364. {
  3365. return "Valve Client";
  3366. }
  3367. //-----------------------------------------------------------------------------
  3368. // Purpose: Handles windows messages sent to the notify tray icon
  3369. //-----------------------------------------------------------------------------
  3370. static void staticNotifyIconProc(HWND hwnd, WPARAM wparam, LPARAM lparam)
  3371. {
  3372. switch (lparam)
  3373. {
  3374. case WM_LBUTTONDOWN:
  3375. {
  3376. // notify the window of the double click
  3377. if (g_Surface.GetNotifyPanel())
  3378. {
  3379. g_pIVgui->PostMessage(g_pSurface->GetNotifyPanel(), new KeyValues("NotifyIconMsg", "msg", "WM_LBUTTONDOWN"), NULL);
  3380. }
  3381. break;
  3382. }
  3383. case WM_LBUTTONDBLCLK:
  3384. {
  3385. //HACK: always bring us to front if the user double clicks the icon
  3386. ::SetForegroundWindow(hwnd);
  3387. // notify the window of the double click
  3388. if (g_pSurface->GetNotifyPanel())
  3389. {
  3390. g_pIVgui->PostMessage(g_pSurface->GetNotifyPanel(), new KeyValues("NotifyIconMsg", "msg", "LBUTTONDBLCLK"), NULL);
  3391. }
  3392. break;
  3393. }
  3394. case WM_RBUTTONUP: // win95/98/NT
  3395. case WM_CONTEXTMENU: // win2k/ME
  3396. {
  3397. // display context menu
  3398. if (g_pSurface->GetNotifyPanel())
  3399. {
  3400. g_pIVgui->PostMessage(g_pSurface->GetNotifyPanel(), new KeyValues("NotifyIconMsg", "msg", "CONTEXTMENU"), NULL);
  3401. }
  3402. break;
  3403. }
  3404. default:
  3405. break;
  3406. }
  3407. }
  3408. static KeyCode g_iPreviousKeyCode = KEY_NONE;
  3409. static void PostCursorMoved( HWND hwnd, LPARAM lparam )
  3410. {
  3411. POINT pt;
  3412. pt.x = (short)LOWORD(lparam);
  3413. pt.y = (short)HIWORD(lparam);
  3414. ::ClientToScreen( hwnd, &pt);
  3415. g_pInput->InternalCursorMoved(pt.x, pt.y);
  3416. }
  3417. static LRESULT CALLBACK staticProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
  3418. {
  3419. static UINT s_uTaskbarRestart;
  3420. VPANEL panel = NULL;
  3421. IClientPanel *client = NULL;
  3422. if (staticSurfaceAvailable)
  3423. {
  3424. panel = g_pIVgui->HandleToPanel(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
  3425. if (panel)
  3426. {
  3427. client = ((VPanel *)panel)->Client();
  3428. }
  3429. }
  3430. // special case msg handle
  3431. if (msg == staticShutdownMsg)
  3432. {
  3433. // we're being notified that we have to Shutdown
  3434. g_pIVgui->ShutdownMessage(lparam);
  3435. return ::DefWindowProc(hwnd,msg,wparam,lparam);
  3436. }
  3437. if (msg == WM_ENDSESSION && wparam == TRUE)
  3438. {
  3439. // system is being shutdown
  3440. // after this message is processed, the app will be terminated
  3441. // so all necessary shutdown functions need to occur now
  3442. if (g_pSurface->GetEmbeddedPanel())
  3443. {
  3444. g_pIPanel->SendMessage(g_pSurface->GetEmbeddedPanel(), new KeyValues("WindowsEndSession"), NULL);
  3445. }
  3446. return 0;
  3447. }
  3448. if (!panel)
  3449. {
  3450. return ::DefWindowProc(hwnd,msg,wparam,lparam);
  3451. }
  3452. bool sendToDefWindowProc = true;
  3453. // md: temporarily disabled until the infinite recursion gets fixed.
  3454. if ( ImmIsUIMessage( NULL, msg, wparam, lparam ) )
  3455. {
  3456. sendToDefWindowProc = false;
  3457. }
  3458. switch (msg)
  3459. {
  3460. case MS_WM_XBUTTONDOWN:
  3461. {
  3462. PostCursorMoved( hwnd, lparam );
  3463. MouseCode code = ( HIWORD( wparam ) == 1 ) ? MOUSE_4 : MOUSE_5;
  3464. g_pInput->SetMouseCodeState( code, BUTTON_PRESSED );
  3465. g_pInput->InternalMousePressed( code );
  3466. break;
  3467. }
  3468. case MS_WM_XBUTTONUP:
  3469. {
  3470. PostCursorMoved( hwnd, lparam );
  3471. MouseCode code = ( HIWORD( wparam ) == 1 ) ? MOUSE_4 : MOUSE_5;
  3472. g_pInput->SetMouseCodeState( code, BUTTON_RELEASED );
  3473. g_pInput->InternalMouseReleased( code );
  3474. break;
  3475. }
  3476. case MS_WM_XBUTTONDBLCLK:
  3477. {
  3478. PostCursorMoved( hwnd, lparam );
  3479. MouseCode code = ( HIWORD( wparam ) == 1 ) ? MOUSE_4 : MOUSE_5;
  3480. g_pInput->SetMouseCodeState( code, BUTTON_DOUBLECLICKED );
  3481. g_pInput->InternalMouseDoublePressed( code );
  3482. break;
  3483. }
  3484. case WM_CREATE:
  3485. {
  3486. s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
  3487. break;
  3488. }
  3489. case WM_CLOSE:
  3490. {
  3491. // tell the panel to close
  3492. g_pIVgui->PostMessage(panel, new KeyValues("Close"), NULL);
  3493. // don't Run default message pump, as that destroys the window
  3494. return 0;
  3495. }
  3496. case WM_MY_TRAY_NOTIFICATION:
  3497. {
  3498. staticNotifyIconProc(hwnd, wparam, lparam);
  3499. break;
  3500. }
  3501. case WM_SETFOCUS:
  3502. {
  3503. g_Surface.setFocus(panel);
  3504. //g_pIVgui->DPrintf("Set Focus %s %p\n", client->GetName(), panel);
  3505. break;
  3506. }
  3507. case WM_KILLFOCUS:
  3508. {
  3509. g_Surface.setFocus(NULL);
  3510. break;
  3511. }
  3512. case WM_APP:
  3513. {
  3514. g_Surface.setFocus(NULL);
  3515. break;
  3516. }
  3517. case WM_SETCURSOR:
  3518. {
  3519. //!! SetCursor(staticCurrentCursor);
  3520. break;
  3521. }
  3522. case WM_MOUSEMOVE:
  3523. {
  3524. POINT pt;
  3525. pt.x = (short)LOWORD(lparam);
  3526. pt.y = (short)HIWORD(lparam);
  3527. // This code catches the case when a WM_LBUTTONUP is lost
  3528. bool bLMButtonDown = ( wparam & MK_LBUTTON ) ? true : false;
  3529. bool bRMButtonDown = ( wparam & MK_RBUTTON ) ? true : false;
  3530. bool bMMButtonDown = ( wparam & MK_MBUTTON ) ? true : false;
  3531. if ( !bLMButtonDown && g_pInput->IsMouseDown( MOUSE_LEFT ) )
  3532. {
  3533. g_pInput->SetMouseCodeState( MOUSE_LEFT, BUTTON_RELEASED );
  3534. g_pInput->InternalMouseReleased(MOUSE_LEFT);
  3535. }
  3536. if ( !bRMButtonDown && g_pInput->IsMouseDown( MOUSE_RIGHT ) )
  3537. {
  3538. g_pInput->SetMouseCodeState( MOUSE_LEFT, BUTTON_RELEASED );
  3539. g_pInput->InternalMouseReleased(MOUSE_LEFT);
  3540. }
  3541. if ( !bMMButtonDown && g_pInput->IsMouseDown( MOUSE_MIDDLE ) )
  3542. {
  3543. g_pInput->SetMouseCodeState( MOUSE_MIDDLE, BUTTON_RELEASED );
  3544. g_pInput->InternalMouseReleased(MOUSE_MIDDLE);
  3545. }
  3546. ::ClientToScreen((HWND)hwnd, &pt);
  3547. g_pInput->InternalCursorMoved(pt.x, pt.y);
  3548. break;
  3549. }
  3550. case WM_LBUTTONDOWN:
  3551. {
  3552. PostCursorMoved( hwnd, lparam );
  3553. g_pInput->SetMouseCodeState( MOUSE_LEFT, BUTTON_PRESSED );
  3554. g_pInput->InternalMousePressed(MOUSE_LEFT);
  3555. break;
  3556. }
  3557. case WM_RBUTTONDOWN:
  3558. {
  3559. PostCursorMoved( hwnd, lparam );
  3560. g_pInput->SetMouseCodeState( MOUSE_RIGHT, BUTTON_PRESSED );
  3561. g_pInput->InternalMousePressed(MOUSE_RIGHT);
  3562. break;
  3563. }
  3564. case WM_MBUTTONDOWN:
  3565. {
  3566. PostCursorMoved( hwnd, lparam );
  3567. g_pInput->SetMouseCodeState( MOUSE_MIDDLE, BUTTON_PRESSED );
  3568. g_pInput->InternalMousePressed(MOUSE_MIDDLE);
  3569. break;
  3570. }
  3571. case WM_LBUTTONDBLCLK:
  3572. {
  3573. PostCursorMoved( hwnd, lparam );
  3574. g_pInput->SetMouseCodeState( MOUSE_LEFT, BUTTON_DOUBLECLICKED );
  3575. g_pInput->InternalMouseDoublePressed( MOUSE_LEFT );
  3576. break;
  3577. }
  3578. case WM_RBUTTONDBLCLK:
  3579. {
  3580. PostCursorMoved( hwnd, lparam );
  3581. g_pInput->SetMouseCodeState( MOUSE_RIGHT, BUTTON_DOUBLECLICKED );
  3582. g_pInput->InternalMouseDoublePressed( MOUSE_RIGHT );
  3583. break;
  3584. }
  3585. case WM_MBUTTONDBLCLK:
  3586. {
  3587. PostCursorMoved( hwnd, lparam );
  3588. g_pInput->SetMouseCodeState( MOUSE_MIDDLE, BUTTON_DOUBLECLICKED );
  3589. g_pInput->InternalMouseDoublePressed( MOUSE_MIDDLE );
  3590. break;
  3591. }
  3592. case WM_LBUTTONUP:
  3593. {
  3594. PostCursorMoved( hwnd, lparam );
  3595. g_pInput->SetMouseCodeState( MOUSE_LEFT, BUTTON_RELEASED );
  3596. g_pInput->InternalMouseReleased( MOUSE_LEFT );
  3597. break;
  3598. }
  3599. case WM_RBUTTONUP:
  3600. {
  3601. PostCursorMoved( hwnd, lparam );
  3602. g_pInput->SetMouseCodeState( MOUSE_RIGHT, BUTTON_RELEASED );
  3603. g_pInput->InternalMouseReleased( MOUSE_RIGHT );
  3604. break;
  3605. }
  3606. case WM_MBUTTONUP:
  3607. {
  3608. PostCursorMoved( hwnd, lparam );
  3609. g_pInput->SetMouseCodeState( MOUSE_MIDDLE, BUTTON_RELEASED );
  3610. g_pInput->InternalMouseReleased( MOUSE_MIDDLE );
  3611. break;
  3612. }
  3613. case WM_MOUSEWHEEL:
  3614. {
  3615. g_pInput->InternalMouseWheeled(((short)HIWORD(wparam))/WHEEL_DELTA);
  3616. break;
  3617. }
  3618. case WM_KEYDOWN:
  3619. case WM_SYSKEYDOWN:
  3620. {
  3621. int code = wparam;
  3622. g_iPreviousKeyCode = KeyCode_VirtualKeyToVGUI( code );
  3623. bool bRepeating = ( lparam & ( 1<<30 ) ) != 0;
  3624. if ( !bRepeating )
  3625. {
  3626. g_pInput->SetKeyCodeState( g_iPreviousKeyCode, BUTTON_PRESSED );
  3627. g_pInput->InternalKeyCodePressed( g_iPreviousKeyCode );
  3628. }
  3629. g_pInput->InternalKeyCodeTyped( g_iPreviousKeyCode );
  3630. // Deal with toggles
  3631. if ( !bRepeating )
  3632. {
  3633. if ( code == VK_CAPITAL || code == VK_SCROLL || code == VK_NUMLOCK )
  3634. {
  3635. ButtonCode_t toggleCode;
  3636. switch( code )
  3637. {
  3638. default: case VK_CAPITAL: toggleCode = KEY_CAPSLOCKTOGGLE; break;
  3639. case VK_SCROLL: toggleCode = KEY_SCROLLLOCKTOGGLE; break;
  3640. case VK_NUMLOCK: toggleCode = KEY_NUMLOCKTOGGLE; break;
  3641. };
  3642. SHORT wState = GetKeyState( code );
  3643. bool bToggleState = ( wState & 0x1 ) != 0;
  3644. if ( bToggleState )
  3645. {
  3646. g_pInput->SetKeyCodeState( toggleCode, BUTTON_PRESSED );
  3647. g_pInput->InternalKeyCodePressed( toggleCode );
  3648. }
  3649. else
  3650. {
  3651. g_pInput->SetKeyCodeState( toggleCode, BUTTON_RELEASED );
  3652. g_pInput->InternalKeyCodeReleased( toggleCode );
  3653. }
  3654. }
  3655. }
  3656. break;
  3657. }
  3658. case WM_SYSCHAR:
  3659. case WM_CHAR:
  3660. {
  3661. int unichar = wparam;
  3662. g_pInput->InternalKeyTyped(unichar);
  3663. break;
  3664. }
  3665. case WM_KEYUP:
  3666. case WM_SYSKEYUP:
  3667. {
  3668. KeyCode code = KeyCode_VirtualKeyToVGUI( wparam );
  3669. g_pInput->SetKeyCodeState( code, BUTTON_RELEASED );
  3670. g_pInput->InternalKeyCodeReleased( code );
  3671. break;
  3672. }
  3673. case WM_ERASEBKGND:
  3674. {
  3675. //since the vgui Invalidate call does not erase the background
  3676. //this will only be called when windows itselfs wants a Repaint.
  3677. //this is the desired behavior because this call will for the
  3678. //surface and all its children to end up being repainted, which
  3679. //is what you want when windows wants you to Repaint the surface,
  3680. //but not what you want when say a control wants to be painted
  3681. //VPanel::Repaint will always Invalidate the surface so it will
  3682. //get a WM_PAINT, but that does not necessarily mean you want
  3683. //the whole surface painted
  3684. //simply this means.. this call only happens when windows wants the Repaint
  3685. //and WM_PAINT gets called just after this to do the real painting
  3686. client->Repaint();
  3687. // vgui::g_pIVgui->DPrintf( "WM_ERASEBKGND(%X)\n", panel );
  3688. break;
  3689. }
  3690. case WM_PAINT:
  3691. {
  3692. //surface was by repainted vgui or by windows itself, do the repainting all repainting
  3693. //will goes through here and nowhere else
  3694. // post Paint messages to the que
  3695. // panel->SolveTraverse();
  3696. // post a message to Paint the window
  3697. // vgui::g_pIVgui->DPrintf( "WM_PAINT(%X)\n", panel );
  3698. // g_pInput->PostMessage( panel, new KeyValues("Paint"), NULL );
  3699. // this relies on platTick() being called BEFORE dispatchMessages(), so that painting occurs
  3700. // on the same frame that the WM_PAINT message is received
  3701. // double startTime, solveTime, paintTime;
  3702. // OLD CODE
  3703. // check that the panel is visible all the way to the root
  3704. bool IsVisible=g_pIPanel->IsVisible(panel);
  3705. VPANEL p= g_pIPanel->GetParent(panel);
  3706. // drill down the heirachy checking that everything is visible
  3707. while(p && IsVisible)
  3708. {
  3709. if( g_pIPanel->IsVisible(p)==false)
  3710. {
  3711. IsVisible=false;
  3712. break;
  3713. }
  3714. p=g_pIPanel->GetParent(p);
  3715. }
  3716. if( IsVisible )
  3717. {
  3718. PAINTSTRUCT ps;
  3719. ::BeginPaint(hwnd,&ps);
  3720. // startTime = system()->GetCurrentTime();
  3721. g_Surface.SolveTraverse(panel, false);
  3722. // solveTime = system()->GetCurrentTime();
  3723. g_Surface.PaintTraverse(panel);
  3724. // paintTime = system()->GetCurrentTime();
  3725. ::EndPaint(hwnd,&ps);
  3726. }
  3727. // debug timing code
  3728. // ivgui()->DPrintf2("Paint timings (%.3f %.3f)\n", (float)(solveTime - startTime), (float)(paintTime - solveTime));
  3729. /* char dbtxt[200];
  3730. Q_snprintf(dbtxt,200,"paint:%p -- %p\n",hwnd,g_Surface.GetHTMLWindow(0)->GetIEHWND());
  3731. OutputDebugString( dbtxt );
  3732. */
  3733. //clear the update rectangle so it does not get another Repaint
  3734. ::ValidateRect(hwnd, NULL);
  3735. break;
  3736. }
  3737. default:
  3738. {
  3739. if (msg == s_uTaskbarRestart)
  3740. {
  3741. // notify window to re-add taskbar icons
  3742. g_pIVgui->PostMessage(panel, new KeyValues("TaskbarRestart"), NULL);
  3743. }
  3744. break;
  3745. }
  3746. }
  3747. if ( sendToDefWindowProc )
  3748. {
  3749. return DefWindowProc(hwnd,msg,wparam,lparam);
  3750. }
  3751. return TRUE;
  3752. }