Team Fortress 2 Source Code as on 22/4/2020
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.

1794 lines
56 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. // This class is a message box that has two buttons, ok and cancel instead of
  5. // just the ok button of a message box. We use a message box class for the ok button
  6. // and implement another button here.
  7. //
  8. // $NoKeywords: $
  9. //=============================================================================//
  10. #include "vgui_controls/pch_vgui_controls.h"
  11. #include <vgui_controls/EditablePanel.h>
  12. #include <vgui_controls/Menu.h>
  13. #include <vgui_controls/MessageBox.h>
  14. #include "filesystem.h"
  15. #include "../vgui2/src/vgui_key_translation.h"
  16. #undef PostMessage
  17. #undef MessageBox
  18. #include "OfflineMode.h"
  19. // memdbgon must be the last include file in a .cpp file
  20. #include "tier0/memdbgon.h"
  21. using namespace vgui;
  22. //-----------------------------------------------------------------------------
  23. // Purpose: A simple passthrough panel to render the border onto the HTML widget
  24. //-----------------------------------------------------------------------------
  25. class HTMLInterior : public Panel
  26. {
  27. DECLARE_CLASS_SIMPLE( HTMLInterior, Panel );
  28. public:
  29. HTMLInterior( HTML *parent ) : BaseClass( parent, "HTMLInterior" )
  30. {
  31. m_pHTML = parent;
  32. SetPaintBackgroundEnabled( false );
  33. SetKeyBoardInputEnabled( false );
  34. SetMouseInputEnabled( false );
  35. }
  36. private:
  37. HTML *m_pHTML;
  38. };
  39. //-----------------------------------------------------------------------------
  40. // Purpose: container class for any external popup windows the browser requests
  41. //-----------------------------------------------------------------------------
  42. class HTMLPopup : public vgui::Frame
  43. {
  44. DECLARE_CLASS_SIMPLE( HTMLPopup, vgui::Frame );
  45. class PopupHTML : public vgui::HTML
  46. {
  47. DECLARE_CLASS_SIMPLE( PopupHTML, vgui::HTML );
  48. public:
  49. PopupHTML( Frame *parent, const char *pchName, bool allowJavaScript , bool bPopupWindow ) : HTML( parent, pchName, allowJavaScript, bPopupWindow ) { m_pParent = parent; }
  50. virtual void OnSetHTMLTitle( const char *pchTitle )
  51. {
  52. BaseClass::OnSetHTMLTitle( pchTitle );
  53. m_pParent->SetTitle( pchTitle, true );
  54. }
  55. private:
  56. Frame *m_pParent;
  57. };
  58. public:
  59. HTMLPopup( Panel *parent, const char *pchURL, const char *pchTitle ) : Frame( NULL, "HtmlPopup", true )
  60. {
  61. m_pHTML = new PopupHTML( this, "htmlpopupchild", true, true );
  62. m_pHTML->OpenURL( pchURL, NULL, false );
  63. SetTitle( pchTitle, true );
  64. }
  65. ~HTMLPopup()
  66. {
  67. }
  68. enum
  69. {
  70. vert_inset = 40,
  71. horiz_inset = 6
  72. };
  73. void PerformLayout()
  74. {
  75. BaseClass::PerformLayout();
  76. int wide, tall;
  77. GetSize( wide, tall );
  78. m_pHTML->SetPos( horiz_inset, vert_inset );
  79. m_pHTML->SetSize( wide - horiz_inset*2, tall - vert_inset*2 );
  80. }
  81. void SetBounds( int x, int y, int wide, int tall )
  82. {
  83. BaseClass::SetBounds( x, y, wide + horiz_inset*2, tall + vert_inset*2 );
  84. }
  85. MESSAGE_FUNC( OnCloseWindow, "OnCloseWindow" )
  86. {
  87. Close();
  88. }
  89. private:
  90. PopupHTML *m_pHTML;
  91. };
  92. //-----------------------------------------------------------------------------
  93. // Purpose: Constructor
  94. //-----------------------------------------------------------------------------
  95. HTML::HTML(Panel *parent, const char *name, bool allowJavaScript, bool bPopupWindow) : Panel(parent, name),
  96. m_NeedsPaint( this, &HTML::BrowserNeedsPaint ),
  97. m_StartRequest( this, &HTML::BrowserStartRequest ),
  98. m_URLChanged( this, &HTML::BrowserURLChanged ),
  99. m_FinishedRequest( this, &HTML::BrowserFinishedRequest ),
  100. m_LinkInNewTab( this, &HTML::BrowserOpenNewTab ),
  101. m_ChangeTitle( this, &HTML::BrowserSetHTMLTitle ),
  102. m_NewWindow( this, &HTML::BrowserPopupHTMLWindow ),
  103. m_FileLoadDialog( this, &HTML::BrowserFileLoadDialog ),
  104. m_SearchResults( this, &HTML::BrowserSearchResults ),
  105. m_CloseBrowser( this, &HTML::BrowserClose ),
  106. m_HorizScroll( this, &HTML::BrowserHorizontalScrollBarSizeResponse ),
  107. m_VertScroll( this, &HTML::BrowserVerticalScrollBarSizeResponse ),
  108. m_LinkAtPosResp( this, &HTML::BrowserLinkAtPositionResponse ),
  109. m_JSAlert( this, &HTML::BrowserJSAlert ),
  110. m_JSConfirm( this, &HTML::BrowserJSConfirm ),
  111. m_CanGoBackForward( this, &HTML::BrowserCanGoBackandForward ),
  112. m_SetCursor( this, &HTML::BrowserSetCursor ),
  113. m_StatusText( this, &HTML::BrowserStatusText ),
  114. m_ShowTooltip( this, &HTML::BrowserShowToolTip ),
  115. m_UpdateTooltip( this, &HTML::BrowserUpdateToolTip ),
  116. m_HideTooltip( this, &HTML::BrowserHideToolTip )
  117. {
  118. m_iHTMLTextureID = 0;
  119. m_bCanGoBack = false;
  120. m_bCanGoForward = false;
  121. m_bInFind = false;
  122. m_bRequestingDragURL = false;
  123. m_bRequestingCopyLink = false;
  124. m_flZoom = 100.0f;
  125. m_bNeedsFullTextureUpload = false;
  126. m_pInteriorPanel = new HTMLInterior( this );
  127. SetPostChildPaintEnabled( true );
  128. m_unBrowserHandle = INVALID_HTMLBROWSER;
  129. m_SteamAPIContext.Init();
  130. if ( m_SteamAPIContext.SteamHTMLSurface() )
  131. {
  132. m_SteamAPIContext.SteamHTMLSurface()->Init();
  133. SteamAPICall_t hSteamAPICall = m_SteamAPIContext.SteamHTMLSurface()->CreateBrowser( surface()->GetWebkitHTMLUserAgentString(), NULL );
  134. m_SteamCallResultBrowserReady.Set( hSteamAPICall, this, &HTML::OnBrowserReady );
  135. }
  136. else
  137. {
  138. Warning("Unable to access SteamHTMLSurface");
  139. }
  140. m_iScrollBorderX=m_iScrollBorderY=0;
  141. m_bScrollBarEnabled = true;
  142. m_bContextMenuEnabled = true;
  143. m_bNewWindowsOnly = false;
  144. m_iMouseX = m_iMouseY = 0;
  145. m_iDragStartX = m_iDragStartY = 0;
  146. m_nViewSourceAllowedIndex = -1;
  147. m_iWideLastHTMLSize = m_iTalLastHTMLSize = 0;
  148. _hbar = new ScrollBar(this, "HorizScrollBar", false);
  149. _hbar->SetVisible(false);
  150. _hbar->AddActionSignalTarget(this);
  151. _vbar = new ScrollBar(this, "VertScrollBar", true);
  152. _vbar->SetVisible(false);
  153. _vbar->AddActionSignalTarget(this);
  154. m_pFindBar = new HTML::CHTMLFindBar( this );
  155. m_pFindBar->SetZPos( 2 );
  156. m_pFindBar->SetVisible( false );
  157. m_pContextMenu = new Menu( this, "contextmenu" );
  158. m_pContextMenu->AddMenuItem( "#vgui_HTMLBack", new KeyValues( "Command", "command", "back" ), this );
  159. m_pContextMenu->AddMenuItem( "#vgui_HTMLForward", new KeyValues( "Command", "command", "forward" ), this );
  160. m_pContextMenu->AddMenuItem( "#vgui_HTMLReload", new KeyValues( "Command", "command", "reload" ), this );
  161. m_pContextMenu->AddMenuItem( "#vgui_HTMLStop", new KeyValues( "Command", "command", "stop" ), this );
  162. m_pContextMenu->AddSeparator();
  163. m_pContextMenu->AddMenuItem( "#vgui_HTMLCopyUrl", new KeyValues( "Command", "command", "copyurl" ), this );
  164. m_iCopyLinkMenuItemID = m_pContextMenu->AddMenuItem( "#vgui_HTMLCopyLink", new KeyValues( "Command", "command", "copylink" ), this );
  165. m_pContextMenu->AddMenuItem( "#TextEntry_Copy", new KeyValues( "Command", "command", "copy" ), this );
  166. m_pContextMenu->AddMenuItem( "#TextEntry_Paste", new KeyValues( "Command", "command", "paste" ), this );
  167. m_pContextMenu->AddSeparator();
  168. m_nViewSourceAllowedIndex = m_pContextMenu->AddMenuItem( "#vgui_HTMLViewSource", new KeyValues( "Command", "command", "viewsource" ), this );
  169. }
  170. //-----------------------------------------------------------------------------
  171. // Purpose: browser is ready to show pages
  172. //-----------------------------------------------------------------------------
  173. void HTML::OnBrowserReady( HTML_BrowserReady_t *pBrowserReady, bool bIOFailure )
  174. {
  175. m_unBrowserHandle = pBrowserReady->unBrowserHandle;
  176. BrowserResize();
  177. if (!m_sPendingURLLoad.IsEmpty())
  178. {
  179. PostURL( m_sPendingURLLoad, m_sPendingPostData, false );
  180. m_sPendingURLLoad.Clear();
  181. }
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Purpose: Destructor
  185. //-----------------------------------------------------------------------------
  186. HTML::~HTML()
  187. {
  188. m_pContextMenu->MarkForDeletion();
  189. if ( m_SteamAPIContext.SteamHTMLSurface() )
  190. {
  191. m_SteamAPIContext.SteamHTMLSurface()->RemoveBrowser( m_unBrowserHandle );
  192. }
  193. FOR_EACH_VEC( m_vecHCursor, i )
  194. {
  195. // BR FIXME!
  196. // surface()->DeleteCursor( m_vecHCursor[i].m_Cursor );
  197. }
  198. m_vecHCursor.RemoveAll();
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Purpose: Handle message to change our cursor
  202. //-----------------------------------------------------------------------------
  203. void HTML::OnSetCursorVGUI( int cursor )
  204. {
  205. SetCursor( (HCursor)cursor );
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Purpose: sets up colors/fonts/borders
  209. //-----------------------------------------------------------------------------
  210. void HTML::ApplySchemeSettings(IScheme *pScheme)
  211. {
  212. BaseClass::ApplySchemeSettings(pScheme);
  213. BrowserResize();
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Purpose: overrides panel class, paints a texture of the HTML window as a background
  217. //-----------------------------------------------------------------------------
  218. void HTML::Paint()
  219. {
  220. //VPROF_BUDGET( "HTML::Paint()", VPROF_BUDGETGROUP_OTHER_VGUI );
  221. BaseClass::Paint();
  222. if ( m_iHTMLTextureID != 0 )
  223. {
  224. surface()->DrawSetTexture( m_iHTMLTextureID );
  225. int tw = 0, tt = 0;
  226. surface()->DrawSetColor( Color( 255, 255, 255, 255 ) );
  227. GetSize( tw, tt );
  228. surface()->DrawTexturedRect( 0, 0, tw, tt );
  229. }
  230. // If we have scrollbars, we need to draw the bg color under them, since the browser
  231. // bitmap is a checkerboard under them, and they are transparent in the in-game client
  232. if ( m_iScrollBorderX > 0 || m_iScrollBorderY > 0 )
  233. {
  234. int w, h;
  235. GetSize( w, h );
  236. IBorder *border = GetBorder();
  237. int left = 0, top = 0, right = 0, bottom = 0;
  238. if ( border )
  239. {
  240. border->GetInset( left, top, right, bottom );
  241. }
  242. surface()->DrawSetColor( GetBgColor() );
  243. if ( m_iScrollBorderX )
  244. {
  245. surface()->DrawFilledRect( w-m_iScrollBorderX - right, top, w, h - bottom );
  246. }
  247. if ( m_iScrollBorderY )
  248. {
  249. surface()->DrawFilledRect( left, h-m_iScrollBorderY - bottom, w-m_iScrollBorderX - right, h );
  250. }
  251. }
  252. }
  253. //-----------------------------------------------------------------------------
  254. // Purpose: causes a repaint when the layout changes
  255. //-----------------------------------------------------------------------------
  256. void HTML::PerformLayout()
  257. {
  258. BaseClass::PerformLayout();
  259. Repaint();
  260. int vbarInset = _vbar->IsVisible() ? _vbar->GetWide() : 0;
  261. int maxw = GetWide() - vbarInset;
  262. m_pInteriorPanel->SetBounds( 0, 0, maxw, GetTall() );
  263. IScheme *pClientScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "ClientScheme" ) );
  264. int iSearchInsetY = 5;
  265. int iSearchInsetX = 5;
  266. int iSearchTall = 24;
  267. int iSearchWide = 150;
  268. const char *resourceString = pClientScheme->GetResourceString( "HTML.SearchInsetY");
  269. if ( resourceString )
  270. {
  271. iSearchInsetY = atoi(resourceString);
  272. }
  273. resourceString = pClientScheme->GetResourceString( "HTML.SearchInsetX");
  274. if ( resourceString )
  275. {
  276. iSearchInsetX = atoi(resourceString);
  277. }
  278. resourceString = pClientScheme->GetResourceString( "HTML.SearchTall");
  279. if ( resourceString )
  280. {
  281. iSearchTall = atoi(resourceString);
  282. }
  283. resourceString = pClientScheme->GetResourceString( "HTML.SearchWide");
  284. if ( resourceString )
  285. {
  286. iSearchWide = atoi(resourceString);
  287. }
  288. m_pFindBar->SetBounds( GetWide() - iSearchWide - iSearchInsetX - vbarInset, m_pFindBar->BIsHidden() ? -1*iSearchTall-5: iSearchInsetY, iSearchWide, iSearchTall );
  289. }
  290. //-----------------------------------------------------------------------------
  291. // Purpose: updates the underlying HTML surface widgets position
  292. //-----------------------------------------------------------------------------
  293. void HTML::OnMove()
  294. {
  295. BaseClass::OnMove();
  296. // tell cef where we are on the screen so plugins can correctly render
  297. int nPanelAbsX, nPanelAbsY;
  298. ipanel()->GetAbsPos( GetVPanel(), nPanelAbsX, nPanelAbsY );
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Purpose: opens the URL, will accept any URL that IE accepts
  302. //-----------------------------------------------------------------------------
  303. void HTML::OpenURL(const char *URL, const char *postData, bool force)
  304. {
  305. PostURL( URL, postData, force );
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose: opens the URL, will accept any URL that IE accepts
  309. //-----------------------------------------------------------------------------
  310. void HTML::PostURL(const char *URL, const char *pchPostData, bool force)
  311. {
  312. if ( m_unBrowserHandle == INVALID_HTMLBROWSER )
  313. {
  314. m_sPendingURLLoad = URL;
  315. m_sPendingPostData = pchPostData;
  316. return;
  317. }
  318. if ( IsSteamInOfflineMode() && !force )
  319. {
  320. const char *baseDir = getenv("HTML_OFFLINE_DIR");
  321. if ( baseDir )
  322. {
  323. // get the app we need to run
  324. char htmlLocation[_MAX_PATH];
  325. char otherName[128];
  326. char fileLocation[_MAX_PATH];
  327. if ( ! g_pFullFileSystem->FileExists( baseDir ) )
  328. {
  329. Q_snprintf( otherName, sizeof(otherName), "%senglish.html", OFFLINE_FILE );
  330. baseDir = otherName;
  331. }
  332. g_pFullFileSystem->GetLocalCopy( baseDir ); // put this file on disk for IE to load
  333. g_pFullFileSystem->GetLocalPath( baseDir, fileLocation, sizeof(fileLocation) );
  334. Q_snprintf(htmlLocation, sizeof(htmlLocation), "file://%s", fileLocation);
  335. if (m_SteamAPIContext.SteamHTMLSurface())
  336. m_SteamAPIContext.SteamHTMLSurface()->LoadURL( m_unBrowserHandle, htmlLocation, NULL );
  337. }
  338. else
  339. {
  340. if (m_SteamAPIContext.SteamHTMLSurface())
  341. m_SteamAPIContext.SteamHTMLSurface()->LoadURL( m_unBrowserHandle, URL, NULL );
  342. }
  343. }
  344. else
  345. {
  346. if ( pchPostData && Q_strlen(pchPostData) > 0 )
  347. {
  348. if (m_SteamAPIContext.SteamHTMLSurface())
  349. m_SteamAPIContext.SteamHTMLSurface()->LoadURL( m_unBrowserHandle, URL, pchPostData );
  350. }
  351. else
  352. {
  353. if (m_SteamAPIContext.SteamHTMLSurface())
  354. m_SteamAPIContext.SteamHTMLSurface()->LoadURL( m_unBrowserHandle, URL, NULL );
  355. }
  356. }
  357. }
  358. //-----------------------------------------------------------------------------
  359. // Purpose: opens the URL, will accept any URL that IE accepts
  360. //-----------------------------------------------------------------------------
  361. bool HTML::StopLoading()
  362. {
  363. if (m_SteamAPIContext.SteamHTMLSurface())
  364. m_SteamAPIContext.SteamHTMLSurface()->StopLoad( m_unBrowserHandle );
  365. return true;
  366. }
  367. //-----------------------------------------------------------------------------
  368. // Purpose: refreshes the current page
  369. //-----------------------------------------------------------------------------
  370. bool HTML::Refresh()
  371. {
  372. if (m_SteamAPIContext.SteamHTMLSurface())
  373. m_SteamAPIContext.SteamHTMLSurface()->Reload( m_unBrowserHandle );
  374. return true;
  375. }
  376. //-----------------------------------------------------------------------------
  377. // Purpose: Tells the browser control to go back
  378. //-----------------------------------------------------------------------------
  379. void HTML::GoBack()
  380. {
  381. if (m_SteamAPIContext.SteamHTMLSurface())
  382. m_SteamAPIContext.SteamHTMLSurface()->GoBack( m_unBrowserHandle );
  383. }
  384. //-----------------------------------------------------------------------------
  385. // Purpose: Tells the browser control to go forward
  386. //-----------------------------------------------------------------------------
  387. void HTML::GoForward()
  388. {
  389. if (m_SteamAPIContext.SteamHTMLSurface())
  390. m_SteamAPIContext.SteamHTMLSurface()->GoForward( m_unBrowserHandle );
  391. }
  392. //-----------------------------------------------------------------------------
  393. // Purpose: Checks if the browser can go back further
  394. //-----------------------------------------------------------------------------
  395. bool HTML::BCanGoBack()
  396. {
  397. return m_bCanGoBack;
  398. }
  399. //-----------------------------------------------------------------------------
  400. // Purpose: Checks if the browser can go forward further
  401. //-----------------------------------------------------------------------------
  402. bool HTML::BCanGoFoward()
  403. {
  404. return m_bCanGoForward;
  405. }
  406. //-----------------------------------------------------------------------------
  407. // Purpose: handle resizing
  408. //-----------------------------------------------------------------------------
  409. void HTML::OnSizeChanged(int wide,int tall)
  410. {
  411. BaseClass::OnSizeChanged(wide,tall);
  412. UpdateSizeAndScrollBars();
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Purpose: Run javascript in the page
  416. //-----------------------------------------------------------------------------
  417. void HTML::RunJavascript( const char *pchScript )
  418. {
  419. if (m_SteamAPIContext.SteamHTMLSurface())
  420. m_SteamAPIContext.SteamHTMLSurface()->ExecuteJavascript( m_unBrowserHandle, pchScript );
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Purpose: helper to convert UI mouse codes to CEF ones
  424. //-----------------------------------------------------------------------------
  425. ISteamHTMLSurface::EHTMLMouseButton ConvertMouseCodeToCEFCode( MouseCode code )
  426. {
  427. switch( code )
  428. {
  429. default:
  430. case MOUSE_LEFT:
  431. return ISteamHTMLSurface::eHTMLMouseButton_Left;
  432. break;
  433. case MOUSE_RIGHT:
  434. return ISteamHTMLSurface::eHTMLMouseButton_Right;
  435. break;
  436. case MOUSE_MIDDLE:
  437. return ISteamHTMLSurface::eHTMLMouseButton_Middle;
  438. break;
  439. }
  440. }
  441. //-----------------------------------------------------------------------------
  442. // Purpose: passes mouse clicks to the control
  443. //-----------------------------------------------------------------------------
  444. void HTML::OnMousePressed(MouseCode code)
  445. {
  446. m_sDragURL = NULL;
  447. // mouse4 = back button
  448. if ( code == MOUSE_4 )
  449. {
  450. PostActionSignal( new KeyValues( "HTMLBackRequested" ) );
  451. return;
  452. }
  453. if ( code == MOUSE_5 )
  454. {
  455. PostActionSignal( new KeyValues( "HTMLForwardRequested" ) );
  456. return;
  457. }
  458. if ( code == MOUSE_RIGHT && m_bContextMenuEnabled )
  459. {
  460. GetLinkAtPosition( m_iMouseX, m_iMouseY );
  461. Menu::PlaceContextMenu( this, m_pContextMenu );
  462. return;
  463. }
  464. // ask for the focus to come to this window
  465. RequestFocus();
  466. // now tell the browser about the click
  467. // ignore right clicks if context menu has been disabled
  468. if ( code != MOUSE_RIGHT )
  469. {
  470. if (m_SteamAPIContext.SteamHTMLSurface())
  471. m_SteamAPIContext.SteamHTMLSurface()->MouseDown( m_unBrowserHandle, ConvertMouseCodeToCEFCode( code ) );
  472. }
  473. if ( code == MOUSE_LEFT )
  474. {
  475. input()->GetCursorPos( m_iDragStartX, m_iDragStartY );
  476. int htmlx, htmly;
  477. ipanel()->GetAbsPos( GetVPanel(), htmlx, htmly );
  478. GetLinkAtPosition( m_iDragStartX - htmlx, m_iDragStartY - htmly );
  479. m_bRequestingDragURL = true;
  480. // make sure we get notified when the mouse gets released
  481. if ( !m_sDragURL.IsEmpty() )
  482. {
  483. input()->SetMouseCapture( GetVPanel() );
  484. }
  485. }
  486. }
  487. //-----------------------------------------------------------------------------
  488. // Purpose: passes mouse up events
  489. //-----------------------------------------------------------------------------
  490. void HTML::OnMouseReleased(MouseCode code)
  491. {
  492. if ( code == MOUSE_LEFT )
  493. {
  494. input()->SetMouseCapture( NULL );
  495. input()->SetCursorOveride( 0 );
  496. if ( !m_sDragURL.IsEmpty() && input()->GetMouseOver() != GetVPanel() && input()->GetMouseOver() )
  497. {
  498. // post the text as a drag drop to the target panel
  499. KeyValuesAD kv( "DragDrop" );
  500. if ( ipanel()->RequestInfo( input()->GetMouseOver(), kv )
  501. && kv->GetPtr( "AcceptPanel" ) != NULL )
  502. {
  503. VPANEL vpanel = (VPANEL)kv->GetPtr( "AcceptPanel" );
  504. ivgui()->PostMessage( vpanel, new KeyValues( "DragDrop", "text", m_sDragURL.Get() ), GetVPanel() );
  505. }
  506. }
  507. m_sDragURL = NULL;
  508. }
  509. if (m_SteamAPIContext.SteamHTMLSurface())
  510. m_SteamAPIContext.SteamHTMLSurface()->MouseUp( m_unBrowserHandle, ConvertMouseCodeToCEFCode( code ) );
  511. }
  512. //-----------------------------------------------------------------------------
  513. // Purpose: keeps track of where the cursor is
  514. //-----------------------------------------------------------------------------
  515. void HTML::OnCursorMoved(int x,int y)
  516. {
  517. // Only do this when we are over the current panel
  518. if ( vgui::input()->GetMouseOver() == GetVPanel() )
  519. {
  520. m_iMouseX = x;
  521. m_iMouseY = y;
  522. if (m_SteamAPIContext.SteamHTMLSurface())
  523. m_SteamAPIContext.SteamHTMLSurface()->MouseMove( m_unBrowserHandle, m_iMouseX, m_iMouseY );
  524. }
  525. else if ( !m_sDragURL.IsEmpty() )
  526. {
  527. if ( !input()->GetMouseOver() )
  528. {
  529. // we're not over any vgui window, switch to the OS implementation of drag/drop
  530. // BR FIXME
  531. // surface()->StartDragDropText( m_sDragURL );
  532. m_sDragURL = NULL;
  533. }
  534. }
  535. if ( !m_sDragURL.IsEmpty() && !input()->GetCursorOveride() )
  536. {
  537. // if we've dragged far enough (in global coordinates), set to use the drag cursor
  538. int gx, gy;
  539. input()->GetCursorPos( gx, gy );
  540. if ( abs(m_iDragStartX-gx) + abs(m_iDragStartY-gy) > 3 )
  541. {
  542. // input()->SetCursorOveride( dc_alias );
  543. }
  544. }
  545. }
  546. //-----------------------------------------------------------------------------
  547. // Purpose: passes double click events to the browser
  548. //-----------------------------------------------------------------------------
  549. void HTML::OnMouseDoublePressed(MouseCode code)
  550. {
  551. if (m_SteamAPIContext.SteamHTMLSurface())
  552. m_SteamAPIContext.SteamHTMLSurface()->MouseDoubleClick( m_unBrowserHandle, ConvertMouseCodeToCEFCode( code ) );
  553. }
  554. //-----------------------------------------------------------------------------
  555. // Purpose: return the bitmask of any modifier keys that are currently down
  556. //-----------------------------------------------------------------------------
  557. int GetKeyModifiers()
  558. {
  559. // Any time a key is pressed reset modifier list as well
  560. int nModifierCodes = 0;
  561. if (vgui::input()->IsKeyDown( KEY_LCONTROL ) || vgui::input()->IsKeyDown( KEY_RCONTROL ))
  562. nModifierCodes |= ISteamHTMLSurface::k_eHTMLKeyModifier_CtrlDown;
  563. if (vgui::input()->IsKeyDown( KEY_LALT ) || vgui::input()->IsKeyDown( KEY_RALT ))
  564. nModifierCodes |= ISteamHTMLSurface::k_eHTMLKeyModifier_AltDown;
  565. if (vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT ))
  566. nModifierCodes |= ISteamHTMLSurface::k_eHTMLKeyModifier_ShiftDown;
  567. #ifdef OSX
  568. // for now pipe through the cmd-key to be like the control key so we get copy/paste
  569. if (vgui::input()->IsKeyDown( KEY_LWIN ) || vgui::input()->IsKeyDown( KEY_RWIN ))
  570. nModifierCodes |= ISteamHTMLSurface::k_eHTMLKeyModifier_CtrlDown;
  571. #endif
  572. return nModifierCodes;
  573. }
  574. //-----------------------------------------------------------------------------
  575. // Purpose: passes key presses to the browser (we don't current do this)
  576. //-----------------------------------------------------------------------------
  577. void HTML::OnKeyTyped(wchar_t unichar)
  578. {
  579. if (m_SteamAPIContext.SteamHTMLSurface())
  580. m_SteamAPIContext.SteamHTMLSurface()->KeyChar( m_unBrowserHandle, unichar, (ISteamHTMLSurface::EHTMLKeyModifiers)GetKeyModifiers() );
  581. }
  582. //-----------------------------------------------------------------------------
  583. // Purpose: pop up the find dialog
  584. //-----------------------------------------------------------------------------
  585. void HTML::ShowFindDialog()
  586. {
  587. IScheme *pClientScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "ClientScheme" ) );
  588. if ( !pClientScheme )
  589. return;
  590. m_pFindBar->SetVisible( true );
  591. m_pFindBar->RequestFocus();
  592. m_pFindBar->SetText( "" );
  593. m_pFindBar->HideCountLabel();
  594. m_pFindBar->SetHidden( false );
  595. int x = 0, y = 0, h = 0, w = 0;
  596. m_pFindBar->GetBounds( x, y, w, h );
  597. m_pFindBar->SetPos( x, -1*h );
  598. int iSearchInsetY = 0;
  599. const char *resourceString = pClientScheme->GetResourceString( "HTML.SearchInsetY");
  600. if ( resourceString )
  601. {
  602. iSearchInsetY = atoi(resourceString);
  603. }
  604. float flAnimationTime = 0.0f;
  605. resourceString = pClientScheme->GetResourceString( "HTML.SearchAnimationTime");
  606. if ( resourceString )
  607. {
  608. flAnimationTime = atof(resourceString);
  609. }
  610. GetAnimationController()->RunAnimationCommand( m_pFindBar, "ypos", iSearchInsetY, 0.0f, flAnimationTime, AnimationController::INTERPOLATOR_LINEAR );
  611. }
  612. //-----------------------------------------------------------------------------
  613. // Purpose: hide the find dialog
  614. //-----------------------------------------------------------------------------
  615. void HTML::HideFindDialog()
  616. {
  617. IScheme *pClientScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "ClientScheme" ) );
  618. if ( !pClientScheme )
  619. return;
  620. int x = 0, y = 0, h = 0, w = 0;
  621. m_pFindBar->GetBounds( x, y, w, h );
  622. float flAnimationTime = 0.0f;
  623. const char *resourceString = pClientScheme->GetResourceString( "HTML.SearchAnimationTime");
  624. if ( resourceString )
  625. {
  626. flAnimationTime = atof(resourceString);
  627. }
  628. GetAnimationController()->RunAnimationCommand( m_pFindBar, "ypos", -1*h-5, 0.0f, flAnimationTime, AnimationController::INTERPOLATOR_LINEAR );
  629. m_pFindBar->SetHidden( true );
  630. StopFind();
  631. }
  632. //-----------------------------------------------------------------------------
  633. // Purpose: is the find dialog visible?
  634. //-----------------------------------------------------------------------------
  635. bool HTML::FindDialogVisible()
  636. {
  637. return m_pFindBar->IsVisible() && !m_pFindBar->BIsHidden();
  638. }
  639. //-----------------------------------------------------------------------------
  640. // Purpose: passes key presses to the browser
  641. //-----------------------------------------------------------------------------
  642. void HTML::OnKeyCodeTyped(KeyCode code)
  643. {
  644. switch( code )
  645. {
  646. case KEY_PAGEDOWN:
  647. {
  648. int val = _vbar->GetValue();
  649. val += 200;
  650. _vbar->SetValue(val);
  651. break;
  652. }
  653. case KEY_PAGEUP:
  654. {
  655. int val = _vbar->GetValue();
  656. val -= 200;
  657. _vbar->SetValue(val);
  658. break;
  659. }
  660. case KEY_F5:
  661. {
  662. Refresh();
  663. break;
  664. }
  665. case KEY_F:
  666. {
  667. if ( (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL) )
  668. || ( IsOSX() && ( input()->IsKeyDown(KEY_LWIN) || input()->IsKeyDown(KEY_RWIN) ) ) )
  669. {
  670. if ( !FindDialogVisible() )
  671. {
  672. ShowFindDialog();
  673. }
  674. else
  675. {
  676. HideFindDialog();
  677. }
  678. break;
  679. }
  680. }
  681. case KEY_ESCAPE:
  682. {
  683. if ( FindDialogVisible() )
  684. {
  685. HideFindDialog();
  686. break;
  687. }
  688. }
  689. case KEY_TAB:
  690. {
  691. if ( input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL) )
  692. {
  693. // pass control-tab to parent (through baseclass)
  694. BaseClass::OnKeyTyped( code );
  695. return;
  696. }
  697. break;
  698. }
  699. }
  700. if (m_SteamAPIContext.SteamHTMLSurface())
  701. m_SteamAPIContext.SteamHTMLSurface()->KeyDown( m_unBrowserHandle, KeyCode_VGUIToVirtualKey(code), (ISteamHTMLSurface::EHTMLKeyModifiers)GetKeyModifiers() );
  702. }
  703. //-----------------------------------------------------------------------------
  704. // Purpose:
  705. //-----------------------------------------------------------------------------
  706. void HTML::OnKeyCodeReleased(KeyCode code)
  707. {
  708. if (m_SteamAPIContext.SteamHTMLSurface())
  709. m_SteamAPIContext.SteamHTMLSurface()->KeyUp( m_unBrowserHandle, KeyCode_VGUIToVirtualKey( code ), (ISteamHTMLSurface::EHTMLKeyModifiers)GetKeyModifiers() );
  710. }
  711. //-----------------------------------------------------------------------------
  712. // Purpose: scrolls the vertical scroll bar on a web page
  713. //-----------------------------------------------------------------------------
  714. void HTML::OnMouseWheeled(int delta)
  715. {
  716. if (_vbar )
  717. {
  718. int val = _vbar->GetValue();
  719. val -= (delta * 100.0/3.0 ); // 100 for every 3 lines matches chromes code
  720. _vbar->SetValue(val);
  721. }
  722. if (m_SteamAPIContext.SteamHTMLSurface())
  723. m_SteamAPIContext.SteamHTMLSurface()->MouseWheel( m_unBrowserHandle, delta* 100.0/3.0 );
  724. }
  725. //-----------------------------------------------------------------------------
  726. // Purpose: Inserts a custom URL handler
  727. //-----------------------------------------------------------------------------
  728. void HTML::AddCustomURLHandler(const char *customProtocolName, vgui::Panel *target)
  729. {
  730. int index = m_CustomURLHandlers.AddToTail();
  731. m_CustomURLHandlers[index].hPanel = target;
  732. Q_strncpy(m_CustomURLHandlers[index].url, customProtocolName, sizeof(m_CustomURLHandlers[index].url));
  733. }
  734. //-----------------------------------------------------------------------------
  735. // Purpose: shared code for sizing the HTML surface window
  736. //-----------------------------------------------------------------------------
  737. void HTML::BrowserResize()
  738. {
  739. if (m_unBrowserHandle == INVALID_HTMLBROWSER)
  740. return;
  741. int w,h;
  742. GetSize( w, h );
  743. int right = 0, bottom = 0;
  744. // TODO::STYLE
  745. /*
  746. IAppearance *pAppearance = GetAppearance();
  747. int left = 0, top = 0;
  748. if ( pAppearance )
  749. {
  750. pAppearance->GetInset( left, top, right, bottom );
  751. }
  752. */
  753. if ( m_iWideLastHTMLSize != ( w - m_iScrollBorderX - right ) || m_iTalLastHTMLSize != ( h - m_iScrollBorderY - bottom ) )
  754. {
  755. m_iWideLastHTMLSize = w - m_iScrollBorderX - right;
  756. m_iTalLastHTMLSize = h - m_iScrollBorderY - bottom;
  757. if ( m_iTalLastHTMLSize <= 0 )
  758. {
  759. SetTall( 64 );
  760. m_iTalLastHTMLSize = 64 - bottom;
  761. }
  762. {
  763. if (m_SteamAPIContext.SteamHTMLSurface())
  764. m_SteamAPIContext.SteamHTMLSurface()->SetSize( m_unBrowserHandle, m_iWideLastHTMLSize, m_iTalLastHTMLSize );
  765. }
  766. // webkit forgets the scroll offset when you resize (it saves the scroll in a DC and a resize throws away the DC)
  767. // so just tell it after the resize
  768. int scrollV = _vbar->GetValue();
  769. int scrollH = _hbar->GetValue();
  770. if (m_SteamAPIContext.SteamHTMLSurface())
  771. m_SteamAPIContext.SteamHTMLSurface()->SetHorizontalScroll( m_unBrowserHandle, scrollH );
  772. if (m_SteamAPIContext.SteamHTMLSurface())
  773. m_SteamAPIContext.SteamHTMLSurface()->SetVerticalScroll( m_unBrowserHandle, scrollV );
  774. }
  775. }
  776. //-----------------------------------------------------------------------------
  777. // Purpose: when a slider moves causes the IE images to re-render itself
  778. //-----------------------------------------------------------------------------
  779. void HTML::OnSliderMoved()
  780. {
  781. if(_hbar->IsVisible())
  782. {
  783. int scrollX = _hbar->GetValue();
  784. if (m_SteamAPIContext.SteamHTMLSurface())
  785. m_SteamAPIContext.SteamHTMLSurface()->SetHorizontalScroll( m_unBrowserHandle, scrollX );
  786. }
  787. if(_vbar->IsVisible())
  788. {
  789. int scrollY=_vbar->GetValue();
  790. if (m_SteamAPIContext.SteamHTMLSurface())
  791. m_SteamAPIContext.SteamHTMLSurface()->SetVerticalScroll( m_unBrowserHandle, scrollY );
  792. }
  793. // post a message that the slider has moved
  794. PostActionSignal( new KeyValues( "HTMLSliderMoved" ) );
  795. }
  796. //-----------------------------------------------------------------------------
  797. // Purpose: data accessor
  798. //-----------------------------------------------------------------------------
  799. bool HTML::IsScrolledToBottom()
  800. {
  801. if ( !_vbar->IsVisible() )
  802. return true;
  803. return m_scrollVertical.m_nScroll >= m_scrollVertical.m_nMax;
  804. }
  805. //-----------------------------------------------------------------------------
  806. // Purpose: data accessor
  807. //-----------------------------------------------------------------------------
  808. bool HTML::IsScrollbarVisible()
  809. {
  810. return _vbar->IsVisible();
  811. }
  812. //-----------------------------------------------------------------------------
  813. // Purpose: data accessor
  814. //-----------------------------------------------------------------------------
  815. void HTML::SetScrollbarsEnabled(bool state)
  816. {
  817. m_bScrollBarEnabled = state;
  818. }
  819. //-----------------------------------------------------------------------------
  820. // Purpose: data accessor
  821. //-----------------------------------------------------------------------------
  822. void HTML::SetContextMenuEnabled(bool state)
  823. {
  824. m_bContextMenuEnabled = state;
  825. }
  826. //-----------------------------------------------------------------------------
  827. // Purpose: data accessor
  828. //-----------------------------------------------------------------------------
  829. void HTML::SetViewSourceEnabled(bool state)
  830. {
  831. m_pContextMenu->SetItemVisible( m_nViewSourceAllowedIndex, state );
  832. }
  833. //-----------------------------------------------------------------------------
  834. // Purpose: data accessor
  835. //-----------------------------------------------------------------------------
  836. void HTML::NewWindowsOnly( bool state )
  837. {
  838. m_bNewWindowsOnly = state;
  839. }
  840. //-----------------------------------------------------------------------------
  841. // Purpose: called when our children have finished painting
  842. //-----------------------------------------------------------------------------
  843. void HTML::PostChildPaint()
  844. {
  845. BaseClass::PostChildPaint();
  846. // TODO::STYLE
  847. //m_pInteriorPanel->SetPaintAppearanceEnabled( true ); // turn painting back on so the IE hwnd can render this border
  848. }
  849. //-----------------------------------------------------------------------------
  850. // Purpose: Adds a custom header to all requests
  851. //-----------------------------------------------------------------------------
  852. void HTML::AddHeader( const char *pchHeader, const char *pchValue )
  853. {
  854. if (m_SteamAPIContext.SteamHTMLSurface())
  855. m_SteamAPIContext.SteamHTMLSurface()->AddHeader( m_unBrowserHandle, pchHeader, pchValue );
  856. }
  857. //-----------------------------------------------------------------------------
  858. // Purpose:
  859. //-----------------------------------------------------------------------------
  860. void HTML::OnSetFocus()
  861. {
  862. if (m_SteamAPIContext.SteamHTMLSurface())
  863. m_SteamAPIContext.SteamHTMLSurface()->SetKeyFocus( m_unBrowserHandle, true );
  864. BaseClass::OnSetFocus();
  865. }
  866. //-----------------------------------------------------------------------------
  867. // Purpose:
  868. //-----------------------------------------------------------------------------
  869. void HTML::OnKillFocus()
  870. {
  871. BaseClass::OnKillFocus();
  872. // Don't clear the actual html focus if a context menu is what took focus
  873. if ( m_pContextMenu->HasFocus() )
  874. return;
  875. if (m_SteamAPIContext.SteamHTMLSurface())
  876. m_SteamAPIContext.SteamHTMLSurface()->SetKeyFocus( m_unBrowserHandle, false );
  877. }
  878. //-----------------------------------------------------------------------------
  879. // Purpose: webkit is telling us to use this cursor type
  880. //-----------------------------------------------------------------------------
  881. void HTML::OnCommand( const char *pchCommand )
  882. {
  883. if ( !Q_stricmp( pchCommand, "back" ) )
  884. {
  885. PostActionSignal( new KeyValues( "HTMLBackRequested" ) );
  886. }
  887. else if ( !Q_stricmp( pchCommand, "forward" ) )
  888. {
  889. PostActionSignal( new KeyValues( "HTMLForwardRequested" ) );
  890. }
  891. else if ( !Q_stricmp( pchCommand, "reload" ) )
  892. {
  893. Refresh();
  894. }
  895. else if ( !Q_stricmp( pchCommand, "stop" ) )
  896. {
  897. StopLoading();
  898. }
  899. else if ( !Q_stricmp( pchCommand, "viewsource" ) )
  900. {
  901. if (m_SteamAPIContext.SteamHTMLSurface())
  902. m_SteamAPIContext.SteamHTMLSurface()->ViewSource( m_unBrowserHandle );
  903. }
  904. else if ( !Q_stricmp( pchCommand, "copy" ) )
  905. {
  906. if (m_SteamAPIContext.SteamHTMLSurface())
  907. m_SteamAPIContext.SteamHTMLSurface()->CopyToClipboard( m_unBrowserHandle );
  908. }
  909. else if ( !Q_stricmp( pchCommand, "paste" ) )
  910. {
  911. if (m_SteamAPIContext.SteamHTMLSurface())
  912. m_SteamAPIContext.SteamHTMLSurface()->PasteFromClipboard( m_unBrowserHandle );
  913. }
  914. else if ( !Q_stricmp( pchCommand, "copyurl" ) )
  915. {
  916. system()->SetClipboardText( m_sCurrentURL, m_sCurrentURL.Length() );
  917. }
  918. else if ( !Q_stricmp( pchCommand, "copylink" ) )
  919. {
  920. int x, y;
  921. m_pContextMenu->GetPos( x, y );
  922. int htmlx, htmly;
  923. ipanel()->GetAbsPos( GetVPanel(), htmlx, htmly );
  924. m_bRequestingCopyLink = true;
  925. GetLinkAtPosition( x - htmlx, y - htmly );
  926. }
  927. else
  928. BaseClass::OnCommand( pchCommand );
  929. }
  930. //-----------------------------------------------------------------------------
  931. // Purpose: the control wants us to ask the user what file to load
  932. //-----------------------------------------------------------------------------
  933. void HTML::OnFileSelected( const char *pchSelectedFile )
  934. {
  935. const char *ppchSelectedFiles[] = { pchSelectedFile, NULL };
  936. if (m_SteamAPIContext.SteamHTMLSurface())
  937. m_SteamAPIContext.SteamHTMLSurface()->FileLoadDialogResponse( m_unBrowserHandle , ppchSelectedFiles );
  938. m_hFileOpenDialog->Close();
  939. }
  940. //-----------------------------------------------------------------------------
  941. // Purpose: called when the user dismissed the file dialog with no selection
  942. //-----------------------------------------------------------------------------
  943. void HTML::OnFileSelectionCancelled()
  944. {
  945. if (m_SteamAPIContext.SteamHTMLSurface())
  946. m_SteamAPIContext.SteamHTMLSurface()->FileLoadDialogResponse( m_unBrowserHandle, NULL );
  947. m_hFileOpenDialog->Close();
  948. }
  949. //-----------------------------------------------------------------------------
  950. // Purpose: find any text on the html page with this sub string
  951. //-----------------------------------------------------------------------------
  952. void HTML::Find( const char *pchSubStr )
  953. {
  954. m_bInFind = false;
  955. if ( m_sLastSearchString == pchSubStr ) // same string as last time, lets fine next
  956. m_bInFind = true;
  957. m_sLastSearchString = pchSubStr;
  958. if (m_SteamAPIContext.SteamHTMLSurface())
  959. m_SteamAPIContext.SteamHTMLSurface()->Find( m_unBrowserHandle, pchSubStr, m_bInFind, false );
  960. }
  961. //-----------------------------------------------------------------------------
  962. // Purpose: find any text on the html page with this sub string
  963. //-----------------------------------------------------------------------------
  964. void HTML::FindPrevious()
  965. {
  966. if (m_SteamAPIContext.SteamHTMLSurface())
  967. m_SteamAPIContext.SteamHTMLSurface()->Find( m_unBrowserHandle, m_sLastSearchString, m_bInFind, true );
  968. }
  969. //-----------------------------------------------------------------------------
  970. // Purpose: find any text on the html page with this sub string
  971. //-----------------------------------------------------------------------------
  972. void HTML::FindNext()
  973. {
  974. Find( m_sLastSearchString );
  975. }
  976. //-----------------------------------------------------------------------------
  977. // Purpose: stop an outstanding find request
  978. //-----------------------------------------------------------------------------
  979. void HTML::StopFind( )
  980. {
  981. if (m_SteamAPIContext.SteamHTMLSurface())
  982. m_SteamAPIContext.SteamHTMLSurface()->StopFind( m_unBrowserHandle );
  983. m_bInFind = false;
  984. }
  985. //-----------------------------------------------------------------------------
  986. // Purpose: input handler
  987. //-----------------------------------------------------------------------------
  988. void HTML::OnEditNewLine( Panel *pPanel )
  989. {
  990. OnTextChanged( pPanel );
  991. }
  992. //-----------------------h------------------------------------------------------
  993. // Purpose: input handler
  994. //-----------------------------------------------------------------------------
  995. void HTML::OnTextChanged( Panel *pPanel )
  996. {
  997. char rgchText[2048];
  998. m_pFindBar->GetText( rgchText, sizeof( rgchText ) );
  999. Find( rgchText );
  1000. }
  1001. //-----------------------------------------------------------------------------
  1002. // Purpose: helper class for the find bar
  1003. //-----------------------------------------------------------------------------
  1004. HTML::CHTMLFindBar::CHTMLFindBar( HTML *parent ) : EditablePanel( parent, "FindBar" )
  1005. {
  1006. m_pParent = parent;
  1007. m_bHidden = false;
  1008. m_pFindBar = new TextEntry( this, "FindEntry" );
  1009. m_pFindBar->AddActionSignalTarget( parent );
  1010. m_pFindBar->SendNewLine( true );
  1011. m_pFindCountLabel = new Label( this, "FindCount", "" );
  1012. m_pFindCountLabel->SetVisible( false );
  1013. if ( g_pFullFileSystem->FileExists( "resource/layout/htmlfindbar.layout" ) )
  1014. {
  1015. LoadControlSettings( "resource/layout/htmlfindbar.layout" );
  1016. }
  1017. }
  1018. //-----------------------------------------------------------------------------
  1019. // Purpose: button input into the find bar
  1020. //-----------------------------------------------------------------------------
  1021. void HTML::CHTMLFindBar::OnCommand( const char *pchCmd )
  1022. {
  1023. if ( !Q_stricmp( pchCmd, "close" ) )
  1024. {
  1025. m_pParent->HideFindDialog();
  1026. }
  1027. else if ( !Q_stricmp( pchCmd, "previous" ) )
  1028. {
  1029. m_pParent->FindPrevious();
  1030. }
  1031. else if ( !Q_stricmp( pchCmd, "next" ) )
  1032. {
  1033. m_pParent->FindNext();
  1034. }
  1035. else
  1036. BaseClass::OnCommand( pchCmd );
  1037. }
  1038. //-----------------------------------------------------------------------------
  1039. // Purpose: we have a new texture to update
  1040. //-----------------------------------------------------------------------------
  1041. void HTML::BrowserNeedsPaint( HTML_NeedsPaint_t *pCallback )
  1042. {
  1043. int tw = 0, tt = 0;
  1044. if ( m_iHTMLTextureID != 0 )
  1045. {
  1046. tw = m_allocedTextureWidth;
  1047. tt = m_allocedTextureHeight;
  1048. }
  1049. if ( m_iHTMLTextureID != 0 && ( ( _vbar->IsVisible() && pCallback->unScrollY > 0 && abs( (int)pCallback->unScrollY - m_scrollVertical.m_nScroll) > 5 ) || ( _hbar->IsVisible() && pCallback->unScrollX > 0 && abs( (int)pCallback->unScrollX - m_scrollHorizontal.m_nScroll ) > 5 ) ) )
  1050. {
  1051. m_bNeedsFullTextureUpload = true;
  1052. return;
  1053. }
  1054. // update the vgui texture
  1055. if ( m_bNeedsFullTextureUpload || m_iHTMLTextureID == 0 || tw != (int)pCallback->unWide || tt != (int)pCallback->unTall )
  1056. {
  1057. m_bNeedsFullTextureUpload = false;
  1058. if ( m_iHTMLTextureID != 0 )
  1059. surface()->DeleteTextureByID( m_iHTMLTextureID );
  1060. // if the dimensions changed we also need to re-create the texture ID to support the overlay properly (it won't resize a texture on the fly, this is the only control that needs
  1061. // to so lets have a tiny bit more code here to support that)
  1062. m_iHTMLTextureID = surface()->CreateNewTextureID( true );
  1063. surface()->DrawSetTextureRGBAEx( m_iHTMLTextureID, (const unsigned char *)pCallback->pBGRA, pCallback->unWide, pCallback->unTall, IMAGE_FORMAT_BGRA8888 );// BR FIXME - this call seems to shift by some number of pixels?
  1064. m_allocedTextureWidth = pCallback->unWide;
  1065. m_allocedTextureHeight = pCallback->unTall;
  1066. }
  1067. else if ( (int)pCallback->unUpdateWide > 0 && (int)pCallback->unUpdateTall > 0 )
  1068. {
  1069. // same size texture, just bits changing in it, lets twiddle
  1070. surface()->DrawUpdateRegionTextureRGBA( m_iHTMLTextureID, pCallback->unUpdateX, pCallback->unUpdateY, (const unsigned char *)pCallback->pBGRA, pCallback->unUpdateWide, pCallback->unUpdateTall, IMAGE_FORMAT_BGRA8888 );
  1071. }
  1072. else
  1073. {
  1074. surface()->DrawSetTextureRGBAEx( m_iHTMLTextureID, (const unsigned char *)pCallback->pBGRA,pCallback->unWide, pCallback->unTall, IMAGE_FORMAT_BGRA8888 );
  1075. }
  1076. // need a paint next time
  1077. Repaint();
  1078. }
  1079. //-----------------------------------------------------------------------------
  1080. // Purpose: browser wants to start loading this url, do we let it?
  1081. //-----------------------------------------------------------------------------
  1082. bool HTML::OnStartRequest( const char *url, const char *target, const char *pchPostData, bool bIsRedirect )
  1083. {
  1084. if ( !url || !Q_stricmp( url, "about:blank") )
  1085. return true ; // this is just webkit loading a new frames contents inside an existing page
  1086. HideFindDialog();
  1087. // see if we have a custom handler for this
  1088. bool bURLHandled = false;
  1089. for (int i = 0; i < m_CustomURLHandlers.Count(); i++)
  1090. {
  1091. if (!Q_strnicmp(m_CustomURLHandlers[i].url,url, Q_strlen(m_CustomURLHandlers[i].url)))
  1092. {
  1093. // we have a custom handler
  1094. Panel *targetPanel = m_CustomURLHandlers[i].hPanel;
  1095. if (targetPanel)
  1096. {
  1097. PostMessage(targetPanel, new KeyValues("CustomURL", "url", m_CustomURLHandlers[i].url ) );
  1098. }
  1099. bURLHandled = true;
  1100. }
  1101. }
  1102. if (bURLHandled)
  1103. return false;
  1104. if ( m_bNewWindowsOnly && bIsRedirect )
  1105. {
  1106. if ( target && ( !Q_stricmp( target, "_blank" ) || !Q_stricmp( target, "_new" ) ) ) // only allow NEW windows (_blank ones)
  1107. {
  1108. return true;
  1109. }
  1110. else
  1111. {
  1112. return false;
  1113. }
  1114. }
  1115. if ( target && !Q_strlen( target ) )
  1116. {
  1117. m_sCurrentURL = url;
  1118. KeyValues *pMessage = new KeyValues( "OnURLChanged" );
  1119. pMessage->SetString( "url", url );
  1120. pMessage->SetString( "postdata", pchPostData );
  1121. pMessage->SetInt( "isredirect", bIsRedirect ? 1 : 0 );
  1122. PostActionSignal( pMessage );
  1123. }
  1124. return true;
  1125. }
  1126. //-----------------------------------------------------------------------------
  1127. // Purpose: callback from cef thread, load a url please
  1128. //-----------------------------------------------------------------------------
  1129. void HTML::BrowserStartRequest( HTML_StartRequest_t *pCmd )
  1130. {
  1131. bool bRes = OnStartRequest( pCmd->pchURL, pCmd->pchTarget, pCmd->pchPostData, pCmd->bIsRedirect );
  1132. if (m_SteamAPIContext.SteamHTMLSurface())
  1133. m_SteamAPIContext.SteamHTMLSurface()->AllowStartRequest( m_unBrowserHandle, bRes );
  1134. }
  1135. //-----------------------------------------------------------------------------
  1136. // Purpose: browser went to a new url
  1137. //-----------------------------------------------------------------------------
  1138. void HTML::BrowserURLChanged( HTML_URLChanged_t *pCmd )
  1139. {
  1140. m_sCurrentURL = pCmd->pchURL;
  1141. KeyValues *pMessage = new KeyValues( "OnURLChanged" );
  1142. pMessage->SetString( "url", pCmd->pchURL );
  1143. pMessage->SetString( "postdata", pCmd->pchPostData );
  1144. pMessage->SetInt( "isredirect", pCmd->bIsRedirect ? 1 : 0 );
  1145. PostActionSignal( pMessage );
  1146. OnURLChanged( m_sCurrentURL, pCmd->pchPostData, pCmd->bIsRedirect );
  1147. }
  1148. //-----------------------------------------------------------------------------
  1149. // Purpose: finished loading this page
  1150. //-----------------------------------------------------------------------------
  1151. void HTML::BrowserFinishedRequest( HTML_FinishedRequest_t *pCmd )
  1152. {
  1153. PostActionSignal( new KeyValues( "OnFinishRequest", "url", pCmd->pchURL ) );
  1154. if ( pCmd->pchPageTitle && pCmd->pchPageTitle[0] )
  1155. PostActionSignal( new KeyValues( "PageTitleChange", "title", pCmd->pchPageTitle ) );
  1156. CUtlMap < CUtlString, CUtlString > mapHeaders;
  1157. mapHeaders.SetLessFunc( UtlStringLessFunc );
  1158. // headers are no longer reported on loads
  1159. OnFinishRequest( pCmd->pchURL, pCmd->pchPageTitle, mapHeaders );
  1160. }
  1161. //-----------------------------------------------------------------------------
  1162. // Purpose: browser wants to open a new tab
  1163. //-----------------------------------------------------------------------------
  1164. void HTML::BrowserOpenNewTab( HTML_OpenLinkInNewTab_t *pCmd )
  1165. {
  1166. (pCmd);
  1167. // Not supported by default, if a child class overrides us and knows how to handle tabs, then it can do this.
  1168. }
  1169. //-----------------------------------------------------------------------------
  1170. // Purpose: display a new html window
  1171. //-----------------------------------------------------------------------------
  1172. void HTML::BrowserPopupHTMLWindow( HTML_NewWindow_t *pCmd )
  1173. {
  1174. HTMLPopup *p = new HTMLPopup( this, pCmd->pchURL, "" );
  1175. int wide = pCmd->unWide;
  1176. int tall = pCmd->unTall;
  1177. if ( wide == 0 || tall == 0 )
  1178. {
  1179. wide = MAX( 640, GetWide() );
  1180. tall = MAX( 480, GetTall() );
  1181. }
  1182. p->SetBounds( pCmd->unX, pCmd->unY, wide, tall );
  1183. p->SetDeleteSelfOnClose( true );
  1184. if ( pCmd->unX == 0 || pCmd->unY == 0 )
  1185. p->MoveToCenterOfScreen();
  1186. p->Activate();
  1187. }
  1188. //-----------------------------------------------------------------------------
  1189. // Purpose: browser telling us the page title
  1190. //-----------------------------------------------------------------------------
  1191. void HTML::BrowserSetHTMLTitle( HTML_ChangedTitle_t *pCmd )
  1192. {
  1193. PostMessage( GetParent(), new KeyValues( "OnSetHTMLTitle", "title", pCmd->pchTitle ) );
  1194. OnSetHTMLTitle( pCmd->pchTitle );
  1195. }
  1196. //-----------------------------------------------------------------------------
  1197. // Purpose: status bar details
  1198. //-----------------------------------------------------------------------------
  1199. void HTML::BrowserStatusText( HTML_StatusText_t *pCmd )
  1200. {
  1201. PostActionSignal( new KeyValues( "OnSetStatusText", "status", pCmd->pchMsg ) );
  1202. }
  1203. //-----------------------------------------------------------------------------
  1204. // Purpose: browser telling us to use this cursor
  1205. //-----------------------------------------------------------------------------
  1206. void HTML::BrowserSetCursor( HTML_SetCursor_t *pCmd )
  1207. {
  1208. vgui::CursorCode cursor = dc_last;
  1209. switch ( pCmd->eMouseCursor )
  1210. {
  1211. case ISteamHTMLSurface::dc_user:
  1212. cursor = dc_user;
  1213. break;
  1214. case ISteamHTMLSurface::dc_none:
  1215. cursor = dc_none;
  1216. break;
  1217. default:
  1218. case ISteamHTMLSurface::dc_arrow:
  1219. cursor = dc_arrow;
  1220. break;
  1221. case ISteamHTMLSurface::dc_ibeam:
  1222. cursor = dc_ibeam;
  1223. break;
  1224. case ISteamHTMLSurface::dc_hourglass:
  1225. cursor = dc_hourglass;
  1226. break;
  1227. case ISteamHTMLSurface::dc_waitarrow:
  1228. cursor = dc_waitarrow;
  1229. break;
  1230. case ISteamHTMLSurface::dc_crosshair:
  1231. cursor = dc_crosshair;
  1232. break;
  1233. case ISteamHTMLSurface::dc_up:
  1234. cursor = dc_up;
  1235. break;
  1236. /*case ISteamHTMLSurface::dc_sizenw:
  1237. cursor = dc_sizenw;
  1238. break;
  1239. case ISteamHTMLSurface::dc_sizese:
  1240. cursor = dc_sizese;
  1241. break;
  1242. case ISteamHTMLSurface::dc_sizene:
  1243. cursor = dc_sizene;
  1244. break;
  1245. case ISteamHTMLSurface::dc_sizesw:
  1246. cursor = dc_sizesw;
  1247. break;
  1248. case ISteamHTMLSurface::dc_sizew:
  1249. cursor = dc_sizew;
  1250. break;
  1251. case ISteamHTMLSurface::dc_sizee:
  1252. cursor = dc_sizee;
  1253. break;
  1254. case ISteamHTMLSurface::dc_sizen:
  1255. cursor = dc_sizen;
  1256. break;
  1257. case ISteamHTMLSurface::dc_sizes:
  1258. cursor = dc_sizes;
  1259. break;*/
  1260. case ISteamHTMLSurface::dc_sizewe:
  1261. cursor = dc_sizewe;
  1262. break;
  1263. case ISteamHTMLSurface::dc_sizens:
  1264. cursor = dc_sizens;
  1265. break;
  1266. case ISteamHTMLSurface::dc_sizeall:
  1267. cursor = dc_sizeall;
  1268. break;
  1269. case ISteamHTMLSurface::dc_no:
  1270. cursor = dc_no;
  1271. break;
  1272. case ISteamHTMLSurface::dc_hand:
  1273. cursor = dc_hand;
  1274. break;
  1275. case ISteamHTMLSurface::dc_blank:
  1276. cursor = dc_blank;
  1277. break;
  1278. /* case ISteamHTMLSurface::dc_middle_pan:
  1279. cursor = dc_middle_pan;
  1280. break;
  1281. case ISteamHTMLSurface::dc_north_pan:
  1282. cursor = dc_north_pan;
  1283. break;
  1284. case ISteamHTMLSurface::dc_north_east_pan:
  1285. cursor = dc_north_east_pan;
  1286. break;
  1287. case ISteamHTMLSurface::dc_east_pan:
  1288. cursor = dc_east_pan;
  1289. break;
  1290. case ISteamHTMLSurface::dc_south_east_pan:
  1291. cursor = dc_south_east_pan;
  1292. break;
  1293. case ISteamHTMLSurface::dc_south_pan:
  1294. cursor = dc_south_pan;
  1295. break;
  1296. case ISteamHTMLSurface::dc_south_west_pan:
  1297. cursor = dc_south_west_pan;
  1298. break;
  1299. case ISteamHTMLSurface::dc_west_pan:
  1300. cursor = dc_west_pan;
  1301. break;
  1302. case ISteamHTMLSurface::dc_north_west_pan:
  1303. cursor = dc_north_west_pan;
  1304. break;
  1305. case ISteamHTMLSurface::dc_alias:
  1306. cursor = dc_alias;
  1307. break;
  1308. case ISteamHTMLSurface::dc_cell:
  1309. cursor = dc_cell;
  1310. break;
  1311. case ISteamHTMLSurface::dc_colresize:
  1312. cursor = dc_colresize;
  1313. break;
  1314. case ISteamHTMLSurface::dc_copycur:
  1315. cursor = dc_copycur;
  1316. break;
  1317. case ISteamHTMLSurface::dc_verticaltext:
  1318. cursor = dc_verticaltext;
  1319. break;
  1320. case ISteamHTMLSurface::dc_rowresize:
  1321. cursor = dc_rowresize;
  1322. break;
  1323. case ISteamHTMLSurface::dc_zoomin:
  1324. cursor = dc_zoomin;
  1325. break;
  1326. case ISteamHTMLSurface::dc_zoomout:
  1327. cursor = dc_zoomout;
  1328. break;
  1329. case ISteamHTMLSurface::dc_custom:
  1330. cursor = dc_custom;
  1331. break;
  1332. case ISteamHTMLSurface::dc_help:
  1333. cursor = dc_help;
  1334. break;*/
  1335. }
  1336. if ( cursor >= dc_last )
  1337. {
  1338. cursor = dc_arrow;
  1339. }
  1340. SetCursor( cursor );
  1341. }
  1342. //-----------------------------------------------------------------------------
  1343. // Purpose: browser telling to show the file loading dialog
  1344. //-----------------------------------------------------------------------------
  1345. void HTML::BrowserFileLoadDialog( HTML_FileOpenDialog_t *pCmd )
  1346. {
  1347. // couldn't access an OS-specific dialog, use the internal one
  1348. if ( m_hFileOpenDialog.Get() )
  1349. {
  1350. delete m_hFileOpenDialog.Get();
  1351. m_hFileOpenDialog = NULL;
  1352. }
  1353. m_hFileOpenDialog = new FileOpenDialog( this, pCmd->pchTitle, true );
  1354. m_hFileOpenDialog->SetStartDirectory( pCmd->pchInitialFile );
  1355. m_hFileOpenDialog->AddActionSignalTarget( this );
  1356. m_hFileOpenDialog->SetAutoDelete( true );
  1357. m_hFileOpenDialog->DoModal(false);
  1358. }
  1359. //-----------------------------------------------------------------------------
  1360. // Purpose: browser asking to show a tooltip
  1361. //-----------------------------------------------------------------------------
  1362. void HTML::BrowserShowToolTip( HTML_ShowToolTip_t *pCmd )
  1363. {
  1364. /*
  1365. BR FIXME
  1366. Tooltip *tip = GetTooltip();
  1367. tip->SetText( pCmd->text().c_str() );
  1368. tip->SetTooltipFormatToMultiLine();
  1369. tip->SetTooltipDelayMS( 250 );
  1370. tip->SetMaxToolTipWidth( MAX( 200, GetWide()/2 ) );
  1371. tip->ShowTooltip( this );
  1372. */
  1373. }
  1374. //-----------------------------------------------------------------------------
  1375. // Purpose: browser telling us to update tool tip text
  1376. //-----------------------------------------------------------------------------
  1377. void HTML::BrowserUpdateToolTip( HTML_UpdateToolTip_t *pCmd )
  1378. {
  1379. // GetTooltip()->SetText( pCmd->text().c_str() );
  1380. }
  1381. //-----------------------------------------------------------------------------
  1382. // Purpose: browser telling that it is done with the tip
  1383. //-----------------------------------------------------------------------------
  1384. void HTML::BrowserHideToolTip( HTML_HideToolTip_t *pCmd )
  1385. {
  1386. // GetTooltip()->HideTooltip();
  1387. // DeleteToolTip();
  1388. }
  1389. //-----------------------------------------------------------------------------
  1390. // Purpose: callback when performing a search
  1391. //-----------------------------------------------------------------------------
  1392. void HTML::BrowserSearchResults( HTML_SearchResults_t *pCmd )
  1393. {
  1394. if ( pCmd->unResults == 0 )
  1395. m_pFindBar->HideCountLabel();
  1396. else
  1397. m_pFindBar->ShowCountLabel();
  1398. if ( pCmd->unResults > 0 )
  1399. m_pFindBar->SetDialogVariable( "findcount", (int)pCmd->unResults );
  1400. if ( pCmd->unCurrentMatch > 0 )
  1401. m_pFindBar->SetDialogVariable( "findactive", (int)pCmd->unCurrentMatch );
  1402. m_pFindBar->InvalidateLayout();
  1403. }
  1404. //-----------------------------------------------------------------------------
  1405. // Purpose: browser telling us it had a close requested
  1406. //-----------------------------------------------------------------------------
  1407. void HTML::BrowserClose( HTML_CloseBrowser_t *pCmd )
  1408. {
  1409. PostActionSignal( new KeyValues( "OnCloseWindow" ) );
  1410. }
  1411. //-----------------------------------------------------------------------------
  1412. // Purpose: browser telling us the size of the horizontal scrollbars
  1413. //-----------------------------------------------------------------------------
  1414. void HTML::BrowserHorizontalScrollBarSizeResponse( HTML_HorizontalScroll_t *pCmd )
  1415. {
  1416. ScrollData_t scrollHorizontal;
  1417. scrollHorizontal.m_nScroll = pCmd->unScrollCurrent;
  1418. scrollHorizontal.m_nMax = pCmd->unScrollMax;
  1419. scrollHorizontal.m_bVisible = pCmd->bVisible;
  1420. scrollHorizontal.m_flZoom = pCmd->flPageScale;
  1421. if ( scrollHorizontal != m_scrollHorizontal )
  1422. {
  1423. m_scrollHorizontal = scrollHorizontal;
  1424. UpdateSizeAndScrollBars();
  1425. m_bNeedsFullTextureUpload = true;
  1426. }
  1427. else
  1428. m_scrollHorizontal = scrollHorizontal;
  1429. }
  1430. //-----------------------------------------------------------------------------
  1431. // Purpose: browser telling us the size of the vertical scrollbars
  1432. //-----------------------------------------------------------------------------
  1433. void HTML::BrowserVerticalScrollBarSizeResponse( HTML_VerticalScroll_t *pCmd )
  1434. {
  1435. ScrollData_t scrollVertical;
  1436. scrollVertical.m_nScroll = pCmd->unScrollCurrent;
  1437. scrollVertical.m_nMax = pCmd->unScrollMax;
  1438. scrollVertical.m_bVisible = pCmd->bVisible;
  1439. scrollVertical.m_flZoom = pCmd->flPageScale;
  1440. if ( scrollVertical != m_scrollVertical )
  1441. {
  1442. m_scrollVertical = scrollVertical;
  1443. UpdateSizeAndScrollBars();
  1444. m_bNeedsFullTextureUpload = true;
  1445. }
  1446. else
  1447. m_scrollVertical = scrollVertical;
  1448. }
  1449. //-----------------------------------------------------------------------------
  1450. // Purpose: browser telling us what is at this location on the page
  1451. //-----------------------------------------------------------------------------
  1452. void HTML::BrowserLinkAtPositionResponse( HTML_LinkAtPosition_t *pCmd )
  1453. {
  1454. m_LinkAtPos.m_sURL = pCmd->pchURL;
  1455. m_LinkAtPos.m_nX = pCmd->x;
  1456. m_LinkAtPos.m_nY = pCmd->y;
  1457. m_pContextMenu->SetItemVisible( m_iCopyLinkMenuItemID, !m_LinkAtPos.m_sURL.IsEmpty() ? true : false );
  1458. if ( m_bRequestingDragURL )
  1459. {
  1460. m_bRequestingDragURL = false;
  1461. m_sDragURL = m_LinkAtPos.m_sURL;
  1462. // make sure we get notified when the mouse gets released
  1463. if ( !m_sDragURL.IsEmpty() )
  1464. {
  1465. input()->SetMouseCapture( GetVPanel() );
  1466. }
  1467. }
  1468. if ( m_bRequestingCopyLink )
  1469. {
  1470. m_bRequestingCopyLink = false;
  1471. if ( !m_LinkAtPos.m_sURL.IsEmpty() )
  1472. system()->SetClipboardText( m_LinkAtPos.m_sURL, m_LinkAtPos.m_sURL.Length() );
  1473. else
  1474. system()->SetClipboardText( "", 1 );
  1475. }
  1476. OnLinkAtPosition( m_LinkAtPos.m_sURL );
  1477. }
  1478. //-----------------------------------------------------------------------------
  1479. // Purpose: browser telling us to pop a javascript alert dialog
  1480. //-----------------------------------------------------------------------------
  1481. void HTML::BrowserJSAlert( HTML_JSAlert_t *pCmd )
  1482. {
  1483. MessageBox *pDlg = new MessageBox( m_sCurrentURL, (const char *)pCmd->pchMessage, this );
  1484. pDlg->AddActionSignalTarget( this );
  1485. pDlg->SetCommand( new KeyValues( "DismissJSDialog", "result", false ) );
  1486. pDlg->DoModal();
  1487. }
  1488. //-----------------------------------------------------------------------------
  1489. // Purpose: browser telling us to pop a js confirm dialog
  1490. //-----------------------------------------------------------------------------
  1491. void HTML::BrowserJSConfirm( HTML_JSConfirm_t *pCmd )
  1492. {
  1493. QueryBox *pDlg = new QueryBox( m_sCurrentURL, (const char *)pCmd->pchMessage, this );
  1494. pDlg->AddActionSignalTarget( this );
  1495. pDlg->SetOKCommand( new KeyValues( "DismissJSDialog", "result", true ) );
  1496. pDlg->SetCancelCommand( new KeyValues( "DismissJSDialog", "result", false ) );
  1497. pDlg->DoModal();
  1498. }
  1499. //-----------------------------------------------------------------------------
  1500. // Purpose: got an answer from the dialog, tell cef
  1501. //-----------------------------------------------------------------------------
  1502. void HTML::DismissJSDialog( int bResult )
  1503. {
  1504. if (m_SteamAPIContext.SteamHTMLSurface())
  1505. m_SteamAPIContext.SteamHTMLSurface()->JSDialogResponse( m_unBrowserHandle, bResult );
  1506. };
  1507. //-----------------------------------------------------------------------------
  1508. // Purpose: browser telling us the state of back and forward buttons
  1509. //-----------------------------------------------------------------------------
  1510. void HTML::BrowserCanGoBackandForward( HTML_CanGoBackAndForward_t *pCmd )
  1511. {
  1512. m_bCanGoBack = pCmd->bCanGoBack;
  1513. m_bCanGoForward = pCmd->bCanGoForward;
  1514. }
  1515. //-----------------------------------------------------------------------------
  1516. // Purpose: ask the browser for what is at this x,y
  1517. //-----------------------------------------------------------------------------
  1518. void HTML::GetLinkAtPosition( int x, int y )
  1519. {
  1520. if (m_SteamAPIContext.SteamHTMLSurface())
  1521. m_SteamAPIContext.SteamHTMLSurface()->GetLinkAtPosition( m_unBrowserHandle, x, y );
  1522. }
  1523. //-----------------------------------------------------------------------------
  1524. // Purpose: update the size of the browser itself and scrollbars it shows
  1525. //-----------------------------------------------------------------------------
  1526. void HTML::UpdateSizeAndScrollBars()
  1527. {
  1528. BrowserResize();
  1529. InvalidateLayout();
  1530. }