Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • PantyNabber/fc-pregmod
  • pregmodfan/fc-pregmod
  • Alice.Grant/fc-pregmod
  • powerfful/fc-pregmod
  • elstumpo/fc-pregmod
  • Y/fc-pregmod
  • floer/fc-pregmod
  • oidocrop/fc-pregmod
  • hawk5005/fc-pregmod
  • nn/fc-pregmod
  • latios298/fc-pregmod
  • brpregmodfan/fc-pregmod
  • SomeoneTookMyUserName/fc-pregmod
  • 000-250-006/fc-pregmod
  • rewrica/fc-pregmod
  • Stuffedgame/fc-pregmod
  • wisepants314/fc-pregmod
  • fcanon/fc-pregmod
  • randomanon1/pregmod-mod-cyberfurry
  • teddy.buckland/fc-pregmod
  • farsinian_591b7a2d8b49d/fc-pregmod
  • FCShotadev/fc-pregmod
  • uselessartifact/fc-pregmod
  • irina_90/fc-pregmod
  • thaumx/fc-pregmod
  • MouseOfLight/fc-pregmod
  • empresssela/fc-pregmod
  • MasterAaran/fc-pregmod
  • ishy/fc-pregmod
  • psychofox/fc-pregmod
  • shadomancer/fc-pregmod
  • tycrakgg/fc-pregmod
  • azktaawc/fc-pregmod
  • andonno07/fc-pregmod
  • Onithyr/fc-pregmod
  • redneck987.jl/fc-pregmod
  • Farseeker/fc-pregmod
  • milliarc/fc-pregmod
  • BeefimusMaximus/fc-pregmod
  • magicknight79/fc-pregmod
  • hexall90/fc-pregmod
  • cantworkforever/fc-pregmod
  • jc052005/fc-pregmod
  • klorpa/fc-pregmod
  • doku/fc-pregmod
  • samhradh/fc-pregmod
  • scientist/fc-pregmod
  • albania420/fc-pregmod
  • Editoranon/fc-pregmod
  • Anony/fc-pregmod
  • deimios666/fc-pregmod
  • IvoHoe/fc-pregmod
  • bitty/fc-pregmod
  • RealAnon1800/fc-pregmod
  • brankirk/fc-pregmod
  • Amygdalan/fc-pregmod
  • DankWolf/fc-pregmod
  • Supot1951/fc-pregmod
  • bcy603/fc-pregmod
  • pwfxjpuv/fc-pregmod
  • ThreadAnon/fc-pregmod
  • Anon1800/fc-pregmod
  • Echoart/fc-pregmod
  • Dingotush/fc-pregmod
  • anonman/fc-pregmod
  • Arkerthan/fc-pregmod
  • svornost/fc-pregmod
  • wierdwierdos/fc-pregmod
  • wetwareAnon/fc-pregmod
  • QuartzHat/fc-pregmod
  • IchthysdeKilt/fc-pregmod
  • AnonAnonFC/fc-pregmod
  • Alexsis/fc-pregmod
  • LoyalTreeWP/fc-pregmod
  • aerialace/fc-pregmod
  • NurseryAnon/fc-pregmod
  • drakeashordcataclysm/fc-pregmod
  • AshVaris/fc-pregmod
  • purely0nothing/fc-pregmod
  • alex2011/fc-pregmod
  • Lindontree/fc-pregmod
  • FCaa/fc-pregmod
  • TR-8R/fc-pregmod
  • Jones/fc-pregmod
  • brr99/fc-pregmod
  • WriteAnon101/fc-pregmod
  • Drosil/fc-pregmod
  • Bob1221/fc-pregmod
  • vas/fc-pregmod
  • gitgud.user.937/fc-pregmod
  • D-K/fc-pregmod
  • AnonDev/fc-pregmod
  • madman23456/fc-pregmod
  • InarusLynx/fc-pregmod
  • Sonofrevvan/fc-pregmod
  • Randoisrando/fc-pregmod
  • cheez94/fc-pregmod
  • dldldl/fc-pregmod
  • alice321/fc-pregmod
  • Alexei91/fc-pregmod
  • darkcy/fc-pregmod
  • MapleMAD/fc-pregmod
  • pillarofsalt/fc-pregmod
  • vultureangels/fc-pregmod
  • kernel/fc-pregmod
  • nooneman/fc-pregmod
  • deepmurk/fc-pregmod
  • uglybead/fc-pregmod
  • lemongrab/fc-pregmod
  • temperence-chan/fc-pregmod
  • hcommenter/fc-pregmod
  • SpedeMemerson/fc-pregmod
  • qwijqwsf/fc-pregmod
  • BuDClow/fc-pregmod
  • HiveBro/fc-pregmod
  • shoku/fc-pregmod
  • ezsh/fc-pregmod
  • Blank/fc-pregmod
  • randoralcissian/fc-pregmod
  • benito92/fc-pregmod
  • balakart/fc-pregmod
  • wedonotsaw/fc-pregmod
  • Cayleth/fc-pregmod
  • Khip/fc-pregmod
  • Zfair/fc-pregmod
  • promethium/fc-pregmod
  • scyne/fc-pregmod
  • ZZC/fc-pregmod
  • SilverJanine/fc-pregmod
  • joxosix654email-9.co/fc-pregmod
  • Littlefootlittleguy/fc-pregmod
  • FelipeBA/fc-pregmod
  • bigtiddygothbf/fc-pregmod
  • Qotsafan/fc-pregmod
  • Zachpocalypse/fc-pregmod
  • milkanon66/fc-pregmod
  • GreGGoZZ/fc-pregmod
  • drsnarf86/fc-pregmod
  • valen102938/fc-pregmod
  • pregspammer/fc-pregmod
  • ponderin94/fc-pregmod
  • nook/fc-pregmod
  • carnifex34/fc-pregmod-mod-carni
  • SyntheticHigh/fc-pregmod
  • bob112211/fc-pregmod
  • amomynous0/fc-pregmod
  • oxone/fc-pregmod
  • MaxEuwe/fc-pregmod
  • nekoanon/fc-pregmod
  • preglocke/fc-pregmod
  • valen10293847/fc-pregmod
  • 2hu4u/fc-pregmod
  • mayibrad/fc-pregmod
  • Screm/fc-pregmod
  • Ansopedi/fc-pregmod
  • mrchaosbones/fc-pregmod
  • putrid/fc-pregmod
  • Kinnerman/fc-pregmod
  • gungrave1155/fc-pregmod
  • prndev/fc-pregmod
  • weresmilodon/fc-pregmod
  • auxxigobin/fc-pregmod
  • alice-chan/fc-pregmod
  • wigglie/fc-pregmod
  • jrliltfgb/fc-pregmod
  • Lord.alek.shade/fc-pregmod
  • truetailthesquire/fc-pregmod
  • lowercasedonkey/fc-pregmod
  • alice-chan9/fc-pregmod
  • eroglyphics/fc-pregmod
  • taliyent/fc-pregmod
  • zenzombie90/fc-pregmod
  • kjarik/fc-pregmod
  • wriggler/fc-pregmod
  • midnightblue/fc-pregmod
  • faraen/fc-pregmod
  • sigurd.cole/fc-pregmod
  • FCbuganon/fc-pregmod
  • kidkinster/fc-pregmod
  • Kar_Dragon/fc-pregmod
  • Zhafier/fc-pregmod
  • crcaretti/fc-pregmod
  • anond/fc-pregmod
  • tempmania/fc-pregmod
  • Dhanze/fc-pregmod
  • EstaUnCachucha/fc-pregmod
  • oniAnon/fc-pregmod
  • plebian/fc-pregmod
  • maxd569/fc-pregmod
  • Levarn/fc-pregmod
  • pumpkinspice/fc-pregmod
  • GammaXai/fc-pregmod
  • DanBackslide/fc-pregmod
  • i107760/fc-pregmod
  • Absimiliard/fc-pregmod
  • AmbrosiaCheesecake/fc-pregmod
  • fuguer/fc-pregmod
  • Azurel/fc-pregmod
  • Fake_Dev/fc-pregmod
  • ddongsanda/fc-pregmod
  • Combine456/fc-pregmod
  • UnwrappedGodiva/fc-pregmod
  • toyRuberDucky/fc-pregmod
  • zmobie/fc-pregmod
  • chuongk/fc-pregmod
  • BigWalnuts/fc-pregmod
  • Birdstrike/fc-pregmod
  • r3d/fc-pregmod
  • mawspa/fc-pregmod
  • sushila/fc-pregmod
  • DeathShip/fc-pregmod
  • eggrollsandwich/fc-pregmod
  • krayken/fc-pregmod
  • Reman/fc-pregmod
  • dwiafgts/fc-pregmod
  • jort93/fc-pregmod
  • teruterubouzu/fc-pregmod
  • flut/fc-pregmod
  • john-normal/fc-pregmod
  • Jonathan2405/fc-pregmod
  • Tyrgalon/fc-pregmod
  • NovX/fc-pregmod
  • Star1/fc-pregmod
  • Transhumanist01/fc-pregmod
  • m1017242/fc-pregmod
  • Rizal98798/fc-pregmod
  • jamezu369/fc-pregmod
  • thisisawittyname/fc-pregmod
  • KnightBoulegard/fc-pregmod
  • jblack/fc-pregmod
  • Souldrainr/fc-pregmod
  • torbjornhub/fc-pregmod
  • turnop/fc-pregmod
  • breadedpigeon/fc-pregmod
  • fire.maker/fc-pregmod
  • Inahaze/fc-pregmod
  • Waerjak/fc-pregmod
  • Trashman1138/fc-pregmod
  • supanintendo/fc-pregmod
  • _no0neman/fc-pregmod
  • Weslo/fc-pregmod
  • qw89/fc-pregmod
  • EvilDruid/fc-pregmod
  • dt25/fc-pregmod
  • Raou/fc-pregmod
  • DDouFu/fc-pregmod
  • Mauno/fc-pregmod
  • PandemoniumPenguin/fc-pregmod
  • AngelPuppet/fc-pregmod
  • DasUser79/fc-pregmod
  • Keaeag3s/fc-pregmod
  • HazeHazeHaze/fc-pregmod
  • hpotato/fc-pregmod
  • owouchthatbloodyhurt/fc-pregmod
  • v7Silent/fc-pregmod
  • nickylass/fc-pregmod
  • ThePrimer/fc-pregmod
  • PineCone/fc-pregmod
  • bruhmomentum17/fc-pregmod
  • CheatDude/fc-pregmod
  • synnove/fc-pregmod
  • en_bees/fc-pregmod
  • seronis/fc-pregmod
  • Nepidinepnep/fc-pregmod
  • Titanninja/fc-pregmod
  • Elohiem/fc-pregmod
  • cocoajazz/fc-pregmod
  • tfwncagf/fc-pregmod
  • ChunkyMonke/fc-pregmod
  • Dracoman671/fc-pregmod
  • jgl/fc-pregmod
  • Inev/fc-pregmod
  • jbige/fc-pregmod
  • MonsterMate/fc-pregmod
  • Konstantin6961/fc-pregmod
  • darth_ashi/fc-pregmod
  • shinx/fc-pregmod
  • Anu/fc-pregmod
  • Greytide/fc-pregmod
  • Bonafidemetal/fc-pregmod
  • Peje/fc-pregmod
  • Hexfy98/fc-pregmod
  • TooSlow/fc-pregmod
  • SoGu/fc-pregmod
  • CloudyCoffee/fc-pregmod
  • Welptard/fc-pregmod
  • Ploc/fc-pregmod-ploc
  • rain-/fc-pregmod
  • Pecanus/fc-pregmod
  • Jhortrax/fc-pregmod
  • valleytwo/fc-pregmod
  • QCmd/fc-pregmod
  • kung-wada/fc-pregmod
  • LolGaye/fc-pregmod
  • Exspiravit1/fc-pregmod
  • jadeddog/fc-pregmod
  • buster-scruggs/fs-antebellum-revivalism
  • policia123/fc-pregmod
  • evrgentesee/fc-pregmod
  • rko127/fc-pregmod
  • ExcalGrip12/fc-pregmod
  • BlackAion/fc-pregmod
  • Boss2020/fc-pregmod
  • Lawled/fc-pregmod
  • shiro/fc-pregmod
  • Skavenkeri/fc-pregmod
  • PooPooDooDooHead/fc-pregmod
  • Dugee/fc-pregmod
  • Portal124/fc-pregmod-vore
  • Fekenol/fc-pregmod
  • elGuapo/fc-pregmod
  • KelioSteel/fc-pregmod
  • sldlddk/fc-pregmod
  • lumepanter/fc-pregmod
  • ryuhana/fc-pregmod
  • Nene1009yb/fc-pregmod
  • DontAskDontTell/fc-pregmod-extra-events
  • Dulgi/fc-pregmod
  • Jate/fc-pregmod
  • percy365/fc-pregmod
  • franklygeorge/fc-pregmod
  • Dragneel117/fc-pregmod
  • vl96/fc-pregmod
  • Gorlom/fc-economicmod
  • NotAlive/fc-pregmod
  • Heretek/fc-pregmod
  • joeshmo828282/fc-pregmod
  • deswes/fc-pregmod
  • Nanana21/fc-pregmod
  • Gbr6/fc-pregmod
  • RandomNecro/fc-pregmod
  • Trinidad/fc-pregmod
  • anonymousey/fc-pregmod
  • macaronideath/fc-pregmod
  • fcbleh/fc-pregmod
  • jk3000/fc-pregmod
  • Akane/fc-pregmod
  • TheBoi/fc-pregmod
  • Sheenariel/fc-pregmod
  • Metapod/multi-custom
  • Banyanael/fc-pregmod
  • frogge/fc-pregmod
  • idkkk12385/fc-pregmod
  • Mirarara/fc-pregmod
  • DeaDa/fc-pregmod-thedeal
  • CobraCommander/fc-pregmod
  • bicobus/fc-pregmod
  • CardcaptorRLH85/fc-pregmod
  • temp-ui-start/fc-pregmod
  • PresidentConvert/fc-pregmod
  • delizious/fc-pregmod
  • Ducati/fc-pregmod
  • DerangedLoner/fc-pregmod-development-fork
  • ProjectVictory/fc-pregmod
  • forecastle/fc-pregmod
  • Apathy/fc-pregmod
  • indf/fc-pregmod-dev
  • GavAndAlt/fc-pregmod
  • hagamablabla/fc-pregmod
  • Alaco/fc-pregmod
  • DCoded/fc-pregmod
  • LittlePlague/fc-pregmod
  • MissOnahole/fc-pregmod
  • ishy2317/fc-pregmod
  • nielkazama/fc-pregmod
  • Phobos/fc-pregmod
  • kraster/fc-pregmod
  • JasWS/fc-pregmod
  • FelixJS/fc-pregmod
  • NCherfaoui/fc-pregmod
  • MidnightMoose/fc-pregmod
  • jjjjjj/fc-pregmod
  • Cl0ver/fc-pregmod
  • Pythoniqus/fc-pregmod
  • JohnMolotov/fc-pregmod
  • anonymouspregmodder/fc-pregmod-anonymouspregmodder
  • Fanatey/fc-pregmod
  • Mizako/fc-pregmod
  • Nithhogg/fc-pregmod
  • Bluecoffee/fc-pregmod
380 results
Show changes
Showing
with 1921 additions and 0 deletions
# Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
# OVERVIEW
#
# CMake is a cross-platform open-source build system that can generate project
# files in many different formats. It can be downloaded from
# http://www.cmake.org or installed via a platform package manager.
#
# CMake-generated project formats that have been tested with this CEF binary
# distribution include:
#
# Linux: Ninja, Unix Makefiles
# Mac OS X: Ninja, Xcode 5+
# Windows: Ninja, Visual Studio 2010+
#
# Ninja is a cross-platform open-source tool for running fast builds using
# pre-installed platform toolchains (GNU, clang, Xcode or MSVC). It can be
# downloaded from http://martine.github.io/ninja/ or installed via a platform
# package manager.
#
# BUILD REQUIREMENTS
#
# The below requirements must be met to build this project.
#
# - Chromium Embedded Framework (CEF) 89.0 or newer.
#
# - CMake version 2.8.12.1 or newer.
#
# - Linux/MacOS requirements:
# I haven't tested these platforms. Shouldn't be too hard to add, check the CEF
# distribution and treat FCHost like tests/cefsimple (from which it is derived).
#
# - Windows requirements:
# Visual Studio 2019 or newer.
#
# BUILD EXAMPLES
#
# The below commands will generate project files and create a Debug build of all
# CEF targets using CMake and the platform toolchain.
#
# Start by creating and entering the CMake build output directory:
# > cd path/to/cef_binary_*
# > mkdir build && cd build
#
# To perform a Linux build using a 32-bit CEF binary distribution on a 32-bit
# Linux platform or a 64-bit CEF binary distribution on a 64-bit Linux platform:
# Using Unix Makefiles:
# > cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug ..
# > make -j4 cefclient cefsimple
#
# Using Ninja:
# > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..
# > ninja cefclient cefsimple
#
# To perform a Mac OS X build using a 64-bit CEF binary distribution:
# Using the Xcode IDE:
# > cmake -G "Xcode" -DPROJECT_ARCH="x86_64" ..
# Open build\cef.xcodeproj in Xcode and select Product > Build.
#
# Using Ninja:
# > cmake -G "Ninja" -DPROJECT_ARCH="x86_64" -DCMAKE_BUILD_TYPE=Debug ..
# > ninja cefclient cefsimple
#
# To perform a Windows build using a 32-bit CEF binary distribution:
# Using the Visual Studio 2019 IDE:
# > cmake -G "Visual Studio 16" ..
# Open build\cef.sln in Visual Studio and select Build > Build Solution.
#
# Using Ninja with Visual Studio 2019 command-line tools:
# (this path may be different depending on your Visual Studio installation)
# > "C:\Program Files (x86)\Microsoft Visual Studio 16.0\VC\bin\vcvars32.bat"
# > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..
# > ninja cefclient cefsimple
#
# To perform a Windows build using a 64-bit CEF binary distribution:
# Using the Visual Studio 2019 IDE:
# > cmake -G "Visual Studio 16 Win64" ..
# Open build\cef.sln in Visual Studio and select Build > Build Solution.
#
# Using Ninja with Visual Studio 2019 command-line tools:
# (this path may be different depending on your Visual Studio installation)
# > "C:\Program Files (x86)\Microsoft Visual Studio 16.0\VC\bin\amd64\vcvars64.bat"
# > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..
# > ninja cefclient cefsimple
#
# Global setup.
#
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
# Only generate Debug and Release configuration types.
set(CMAKE_CONFIGURATION_TYPES Debug Release)
# Project name.
project(fchost)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Use folders in the resulting project files.
set_property(GLOBAL PROPERTY OS_FOLDERS ON)
#
# CEF configuration.
#
# Specify the CEF distribution version.
# Visit https://cef-builds.spotifycdn.com/index.html for the list of
# supported platforms and versions.
set(CEF_VERSION "126.2.11+gb281f7a+chromium-126.0.6478.127")
# Determine the platform.
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
if("${PROJECT_ARCH}" STREQUAL "arm64")
set(CEF_PLATFORM "macosarm64")
elseif("${PROJECT_ARCH}" STREQUAL "x86_64")
set(CEF_PLATFORM "macosx64")
elseif("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "arm64")
set(PROJECT_ARCH "arm64")
set(CEF_PLATFORM "macosarm64")
else()
set(PROJECT_ARCH "x86_64")
set(CEF_PLATFORM "macosx64")
endif()
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm")
set(CEF_PLATFORM "linuxarm")
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64")
set(CEF_PLATFORM "linuxarm64")
elseif(CMAKE_SIZEOF_VOID_P MATCHES 8)
set(CEF_PLATFORM "linux64")
else()
message(FATAL_ERROR "Linux x86 32-bit builds are discontinued.")
endif()
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
if("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM64")
set(CEF_PLATFORM "windowsarm64")
elseif(CMAKE_SIZEOF_VOID_P MATCHES 8)
set(CEF_PLATFORM "windows64")
else()
set(CEF_PLATFORM "windows32")
endif()
endif()
# Add this project's cmake/ directory to the module path.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Download and extract the CEF binary distribution (executes DownloadCEF.cmake).
include(DownloadCEF)
DownloadCEF("${CEF_PLATFORM}" "${CEF_VERSION}" "${CMAKE_SOURCE_DIR}/libs")
# Add the CEF binary distribution's cmake/ directory to the module path.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CEF_ROOT}/cmake")
# Load the CEF configuration (executes FindCEF.cmake).
find_package(CEF REQUIRED)
#
# Define CEF-based targets.
#
# Include the libcef_dll_wrapper target.
add_subdirectory(${CEF_LIBCEF_DLL_WRAPPER_PATH} libcef_dll_wrapper)
# Allow includes relative to the current source directory.
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
# Include application targets.
add_subdirectory(fchost)
# Display configuration settings.
PRINT_CEF_CONFIG()
# How to Build
## BUILD REQUIREMENTS
The below requirements must be met to build this project.
- CMake version 2.8.12.1 or newer
- Ensure the CMake binary folder is added to your path (e.g. for Windows `C:\Program Files\CMake\bin`)
- Chromium Embedded Framework (CEF) 126.1 or newer
- Running CMake will automatically download this so there is no need to configure it yourself
### Windows
Visual Studio 2019 (the community edition will work fine) or newer with the "Desktop development with C++" workload installed.
### Linux
Ensure you have a C++ compiler installed. On Debian/Ubuntu this can be installed with:
```bash
sudo apt install build-essential
```
## BUILD STEPS
### Windows
Assuming that Visual Studio 2019/2022 is being used, run the following command:
```bash
# For Visual Studio 2019
# Alternatively run `cmake_vs2019.bat`
cmake -G "Visual Studio 16" .
# For Visual Studio 2022
# Alternatively run `cmake_vs2022.bat`
cmake -G "Visual Studio 17" .
```
Open the generated `fchost.sln` file in Visual Studio. Then build the project by either:
- Selecting **Build > Build Solution** on the menu bar
- Pressing **Ctrl + Shift + B**
### Linux
Run the following commands:
```bash
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .
make -j4
```
### Output
The resulting binary and supporting files will be in `FCHost/fchost/Debug` or `FCHost/fchost/Release` depending on the configuration selected in Visual Studio via the drop down found under the Build and Debug tool bar headers.
You should be able to zip up the contents of the Release folder and distribute them to another machine or user if desired. Due to space and privacy concerns it is suggested that you remove `*.html` and `fchost.ilk` files (if present) prior to distribution.
// FCHost is derived from the CEFSimple example. Original license follows:
//
// Copyright (c) 2008-2014 Marshall A. Greenblatt. Portions Copyright (c)
// 2006-2009 Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<!-- cSpell:ignore fchost, Shokusku's -->
# FCHost
FCHost is an alternative HTML renderer for playing Pregmod based on Chromium. It has multiple advantages compared to normal browsers:
- No browser cache limits, allowing arbitrarily large save files.
- Saves are stored in an easily accessible way on disk, allowing for easy manual editing.
- No lost saves due to accidentally cleared cookies.
- Can be noticeable faster.
A Windows build is available for [download](https://mega.nz/file/kY5GmLRa#jwwgshNuKz0yAQDDeSs-jbPOOGX4Ap1ha_EKlWp-9-M).
If you are developing FC using the advanced tooling then you can run `FCHost.bat` (Windows) or `FCHost.sh` (Mac/Linux) to download and setup FCHost automatically.
## Initial setup
### HTML files
Place `FC_pregmod.html` next to the FCHost executable. This is usually `fchost.exe`, but it may be a file named `fchost` on Mac/Linux.
### Art resources
Art resources work the same way as with other browser. For embedded art no actions are necessary, while for the others
the art resources have to be placed in a `resources` directory next to the HTML file.
Elohiem's interactive WebGL:
- fchost.exe
- resources/
- webgl
Shokusku's rendered image pack
- fchost.exe
- resources/
- dynamic
- renders
If making changes while the game is open make sure to refresh or restart FCHost before trying the art styles.
## Keybinds
| Action | Key Combination |
| --------- | ---------------- |
| Zoom In | Ctrl + Plus |
| Zoom Out | Ctrl + Minus |
| Dev Tools | Ctrl + Shift + J |
## Save file locations
| Platform | Location |
| -------- | -------------------------------------------------------------- |
| Windows | `%User%\Documents\FreeCities_Pregmod\FCHostPersistentStorage\` |
| Linux | `~/.local/share/FreeCities_Pregmod/FCHostPersistentStorage/` |
## Building FCHost
If you want to build FCHost yourself please refer to [FCHost/HowToBuild.md](FCHost/HowToBuild.md).
# Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
# Download the CEF binary distribution for |platform| and |version| to
# |download_dir|. The |CEF_ROOT| variable will be set in global scope pointing
# to the extracted location.
# Visit https://cef-builds.spotifycdn.com/index.html for the list of
# supported platforms and versions.
function(DownloadCEF platform version download_dir)
# Specify the binary distribution type and download directory.
set(CEF_DISTRIBUTION "cef_binary_${version}_${platform}")
set(CEF_DOWNLOAD_DIR "${download_dir}")
# The location where we expect the extracted binary distribution.
set(CEF_ROOT "${CEF_DOWNLOAD_DIR}/${CEF_DISTRIBUTION}" CACHE INTERNAL "CEF_ROOT")
# Download and/or extract the binary distribution if necessary.
if(NOT IS_DIRECTORY "${CEF_ROOT}")
set(CEF_DOWNLOAD_FILENAME "${CEF_DISTRIBUTION}.tar.bz2")
set(CEF_DOWNLOAD_PATH "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}")
if(NOT EXISTS "${CEF_DOWNLOAD_PATH}")
set(CEF_DOWNLOAD_URL "https://cef-builds.spotifycdn.com/${CEF_DOWNLOAD_FILENAME}")
string(REPLACE "+" "%2B" CEF_DOWNLOAD_URL_ESCAPED ${CEF_DOWNLOAD_URL})
# Download the SHA1 hash for the binary distribution.
message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...")
file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1")
file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1)
# Download the binary distribution and verify the hash.
message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}...")
file(
DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}" "${CEF_DOWNLOAD_PATH}"
EXPECTED_HASH SHA1=${CEF_SHA1}
SHOW_PROGRESS
)
endif()
# Extract the binary distribution.
message(STATUS "Extracting ${CEF_DOWNLOAD_PATH}...")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xzf "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}"
WORKING_DIRECTORY ${CEF_DOWNLOAD_DIR}
)
endif()
endfunction()
\ No newline at end of file
@ECHO OFF
REM Quickly rebuild 64-bit VS2019 solution/project files from the CMake files.
cmake -G "Visual Studio 16" -A x64
pause
\ No newline at end of file
@ECHO OFF
REM Quickly rebuild 64-bit VS2022 solution/project files from the CMake files.
cmake -G "Visual Studio 17" -A x64
pause
\ No newline at end of file
# Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
#
# Source files.
#
# fchost sources.
set(FCHOST_SRCS
fchost_app.cc
fchost_app.h
fchost_handler.cc
fchost_handler.h
fchost_storage.cc
fchost_storage.h
fchost_storage_js.cc
fchost_storage_js.h
utility.cc
utility.h
)
set(FCHOST_SRCS_LINUX
fchost_linux.cc
fchost_handler_linux.cc
)
set(FCHOST_SRCS_MACOSX
fchost_mac.mm
fchost_handler_mac.mm
)
set(FCHOST_SRCS_WINDOWS
fchost.exe.manifest
fchost.rc
fchost_win.cc
resource.h
fchost_handler_win.cc
)
APPEND_PLATFORM_SOURCES(FCHOST_SRCS)
source_group(fchost FILES ${FCHOST_SRCS})
set(FCHOST_RES_SRCS_WINDOWS
res/fchost.ico
)
APPEND_PLATFORM_SOURCES(FCHOST_RES_SRCS)
source_group(fchost\\\\res FILES ${FCHOST_RES_SRCS})
set(FCHOST_SRCS
${FCHOST_SRCS}
${FCHOST_RES_SRCS}
)
# fchost helper sources.
set(FCHOST_HELPER_SRCS_MACOSX
process_helper_mac.cc
)
APPEND_PLATFORM_SOURCES(FCHOST_HELPER_SRCS)
source_group(fchost FILES ${FCHOST_HELPER_SRCS})
# fchost resources.
set(FCHOST_RESOURCES_MAC_SRCS_MACOSX
mac/Info.plist
mac/fchost.icns
)
APPEND_PLATFORM_SOURCES(FCHOST_RESOURCES_MAC_SRCS)
source_group(fchost\\\\mac FILES ${FCHOST_RESOURCES_MAC_SRCS})
set(FCHOST_RESOURCES_MAC_ENGLISH_LPROJ_SRCS_MACOSX
mac/English.lproj/InfoPlist.strings
mac/English.lproj/MainMenu.xib
)
APPEND_PLATFORM_SOURCES(FCHOST_RESOURCES_MAC_ENGLISH_LPROJ_SRCS)
source_group(fchost\\\\mac\\\\English.lproj FILES ${FCHOST_RESOURCES_MAC_ENGLISH_LPROJ_SRCS})
set(FCHOST_RESOURCES_SRCS
${FCHOST_RESOURCES_MAC_SRCS}
${FCHOST_RESOURCES_MAC_ENGLISH_LPROJ_SRCS}
)
function (symlink_or_copy_to_binary_dir _target _srcFile)
get_filename_component(_fileName "${_srcFile}" NAME)
if (WIN32)
set(action copy_if_different)
else()
set(action create_symlink)
endif()
add_custom_command(POST_BUILD
TARGET ${_target}
COMMAND ${CMAKE_COMMAND} -E ${action} "${_srcFile}" "$<TARGET_FILE_DIR:${_target}>/${_fileName}"
)
endfunction()
#
# Shared configuration.
#
# Target executable names.
set(CEF_TARGET "fchost")
if(OS_MACOSX)
set(CEF_HELPER_TARGET "fchost_Helper")
set(CEF_HELPER_OUTPUT_NAME "fchost Helper")
else()
# Logical target used to link the libcef library.
ADD_LOGICAL_TARGET("libcef_lib" "${CEF_LIB_DEBUG}" "${CEF_LIB_RELEASE}")
endif()
# Determine the target output directory.
SET_CEF_TARGET_OUT_DIR()
# Executable target.
add_executable(${CEF_TARGET} MACOSX_BUNDLE WIN32 ${FCHOST_SRCS})
set(gameHTMLFile "FC_pregmod.html")
# Link the HTML where the executable expects to find it
symlink_or_copy_to_binary_dir(${CEF_TARGET} "${CMAKE_SOURCE_DIR}/../bin/${gameHTMLFile}")
#
# Linux configuration.
#
if(OS_LINUX)
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
# Set rpath so that libraries can be placed next to the executable.
set_target_properties(${CEF_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN")
set_target_properties(${CEF_TARGET} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
set_target_properties(${CEF_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CEF_TARGET_OUT_DIR})
# Copy binary files to the target output directory.
#COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
foreach(cefBinaryFile IN LISTS CEF_BINARY_FILES)
symlink_or_copy_to_binary_dir(${CEF_TARGET} "${CEF_BINARY_DIR}/${cefBinaryFile}")
endforeach()
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
if (EXISTS "${CEF_BINARY_DIR}/libminigbm.so")
symlink_or_copy_to_binary_dir(${CEF_TARGET} "${CEF_BINARY_DIR}/libminigbm.so")
endif()
endif()
#
# Mac OS X configuration.
#
if(OS_MACOSX)
option(OPTION_USE_ARC "Build with ARC (automatic Reference Counting) on macOS." ON)
if(OPTION_USE_ARC)
list(APPEND CEF_COMPILER_FLAGS
-fobjc-arc
)
set_target_properties(${target} PROPERTIES
CLANG_ENABLE_OBJC_ARC "YES"
)
endif()
# Output paths for the app bundles.
set(CEF_APP "${CEF_TARGET_OUT_DIR}/${CEF_TARGET}.app")
set(CEF_HELPER_APP "${CEF_TARGET_OUT_DIR}/${CEF_HELPER_OUTPUT_NAME}.app")
# Variable referenced from Info.plist files.
set(PRODUCT_NAME "${CEF_TARGET}")
# Helper executable target.
add_executable(${CEF_HELPER_TARGET} MACOSX_BUNDLE ${FCHOST_HELPER_SRCS})
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_HELPER_TARGET})
add_dependencies(${CEF_HELPER_TARGET} libcef_dll_wrapper)
target_link_libraries(${CEF_HELPER_TARGET} libcef_dll_wrapper ${CEF_STANDARD_LIBS})
set_target_properties(${CEF_HELPER_TARGET} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/mac/helper-Info.plist
OUTPUT_NAME ${CEF_HELPER_OUTPUT_NAME}
)
# Main executable target.
target_sources(${CEF_TARGET} ${FCHOST_RESOURCES_SRCS})
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
add_dependencies(${CEF_TARGET} libcef_dll_wrapper "${CEF_HELPER_TARGET}")
target_link_libraries(${CEF_TARGET} libcef_dll_wrapper ${CEF_STANDARD_LIBS})
set_target_properties(${CEF_TARGET} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/mac/Info.plist
)
# Copy files into the main app bundle.
add_custom_command(
TARGET ${CEF_TARGET}
POST_BUILD
# Copy the helper app bundle into the Frameworks directory.
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CEF_HELPER_APP}"
"${CEF_APP}/Contents/Frameworks/${CEF_HELPER_OUTPUT_NAME}.app"
# Copy the CEF framework into the Frameworks directory.
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CEF_BINARY_DIR}/Chromium Embedded Framework.framework"
"${CEF_APP}/Contents/Frameworks/Chromium Embedded Framework.framework"
VERBATIM
)
# Manually process and copy over resource files.
# The Xcode generator can support this via the set_target_properties RESOURCE
# directive but that doesn't properly handle nested resource directories.
# Remove these prefixes from input file paths.
set(PREFIXES "mac/")
COPY_MACOSX_RESOURCES("${FCHOST_RESOURCES_SRCS}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
endif()
#
# Windows configuration.
#
if(OS_WINDOWS)
# Executable target.
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
# Add the custom manifest files to the executable.
ADD_WINDOWS_MANIFEST("${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_TARGET}" "exe")
# Copy binary and resource files to the target output directory.
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
endif()
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!--The ID below indicates application support for Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
</assembly>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<!--The compatibility section will be merged from build/win/compatibility.manifest -->
<dependency>
<dependentAssembly>
<assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_FCHOST ICON "res\fchost.ico"
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "fchost_app.h"
#include "./utility.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/views/cef_browser_view.h"
#include "include/views/cef_window.h"
#include "include/wrapper/cef_helpers.h"
#include "fchost_handler.h"
#include "fchost_storage_js.h"
#include <filesystem>
#include <string>
#if defined(OS_LINUX)
#include <unistd.h>
#endif
namespace {
// When using the Views framework this object provides the delegate
// implementation for the CefWindow that hosts the Views-based browser.
class SimpleWindowDelegate : public CefWindowDelegate {
public:
explicit SimpleWindowDelegate(CefRefPtr<CefBrowserView> browser_view)
: browser_view_(browser_view) {}
void OnWindowCreated(CefRefPtr<CefWindow> window) override {
// Add the browser view and show the window.
window->AddChildView(browser_view_);
window->Show();
// Give keyboard focus to the browser view.
browser_view_->RequestFocus();
}
void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
browser_view_ = nullptr;
}
bool CanClose(CefRefPtr<CefWindow> window) override {
// Allow the window to close if the browser says it's OK.
CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
if (browser)
return browser->GetHost()->TryCloseBrowser();
return true;
}
CefSize GetPreferredSize(CefRefPtr<CefView> view) override {
return CefSize(800, 600);
}
private:
CefRefPtr<CefBrowserView> browser_view_;
IMPLEMENT_REFCOUNTING(SimpleWindowDelegate);
DISALLOW_COPY_AND_ASSIGN(SimpleWindowDelegate);
};
std::filesystem::path executablePath() {
#if defined(OS_WIN)
wchar_t target_path[_MAX_PATH];
GetModuleFileNameW(NULL, target_path, _MAX_PATH);
return std::filesystem::path(target_path);
#elif defined(OS_LINUX)
std::string buf;
buf.resize(32); // initial size estimate
for (;; ) {
ssize_t ret = readlink("/proc/self/exe", buf.data(), buf.size());
if (ret == -1) {
perror("getexename() failed");
break;
}
if (static_cast<std::size_t>(ret) >= buf.size()) { // >= because we need the terminating NUL too
buf.resize(buf.size() * 2);
continue;
}
return buf;
}
return {};
#else
#error "Platform-specific code required"
#endif
}
} // namespace
FCHostApp::FCHostApp() {}
void FCHostApp::OnContextInitialized() {
CEF_REQUIRE_UI_THREAD();
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
#if defined(OS_WIN) || defined(OS_LINUX)
// Create the browser using the Views framework if "--use-views" is specified
// via the command-line. Otherwise, create the browser using the native
// platform framework. The Views framework is currently only supported on
// Windows and Linux.
const bool use_views = command_line->HasSwitch("use-views");
#else
const bool use_views = false;
#endif
// FCHostHandler implements browser-level callbacks.
CefRefPtr<FCHostHandler> handler(new FCHostHandler(use_views));
// Specify CEF browser settings here.
CefBrowserSettings browser_settings;
// Persist local storage
browser_settings.local_storage = STATE_ENABLED;
// For now, read from external file. Probably want to make this a resource
// at least on Windows.
std::filesystem::path gameHTML = executablePath().parent_path() / "FC_pregmod.html";
#if defined(OS_WIN)
std::wstring url = gameHTML.native();
#else
std::string url = "file://" + gameHTML.string();
#endif
if (use_views) {
// Create the BrowserView.
CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
handler, url, browser_settings, nullptr, nullptr, nullptr);
// Create the Window. It will show itself after creation.
CefWindow::CreateTopLevelWindow(new SimpleWindowDelegate(browser_view));
} else {
// Information used when creating the native window.
CefWindowInfo window_info;
#if defined(OS_WIN)
// On Windows we need to specify certain flags that will be passed to
// CreateWindowEx().
window_info.SetAsPopup(NULL, "FCHost");
#endif
// Create the first browser window.
CefBrowserHost::CreateBrowser(window_info, handler, url, browser_settings,
nullptr, nullptr);
}
}
void FCHostApp::OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) {
FCHostStorageRegister(GetLocalStorePath() / "FCHostPersistentStorage", context->GetGlobal());
}
int FCHostApp::main(const CefMainArgs& args, CefCommandLine* commandLine)
{
// Specify CEF global settings here.
CefSettings settings;
if (commandLine->HasSwitch("enable-chrome-runtime")) {
// Enable experimental Chrome runtime. See issue #2969 for details.
settings.chrome_runtime = true;
}
// Cache location is required for local storage
cef_string_from_path(this->GetLocalStorePath(), &settings.cache_path);
// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable
// use of the sandbox.
#if !defined(CEF_USE_SANDBOX)
settings.no_sandbox = true;
#endif
// Initialize CEF for the browser process.
CefInitialize(args, settings, this, nullptr);
// Run the CEF message loop. This will block until CefQuitMessageLoop() is
// called.
CefRunMessageLoop();
// Shut down CEF.
CefShutdown();
return 0;
}
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#pragma once
#include "include/cef_app.h"
#include <filesystem>
class CefMainArgs;
class CefCommandLine;
// Implement application-level callbacks for the browser process.
class FCHostApp : public CefApp, public CefBrowserProcessHandler, public CefRenderProcessHandler {
public:
FCHostApp();
// CefApp methods:
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
override {
return this;
}
virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler()
override {
return this;
}
// CefBrowserProcessHandler methods:
virtual void OnContextInitialized() override;
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) override;
std::filesystem::path GetLocalStorePath();
int main(const CefMainArgs& args, CefCommandLine* commandLine);
private:
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(FCHostApp);
};
This diff is collapsed.
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#pragma once
#include "include/cef_client.h"
#include <list>
class FCHostHandler : public CefClient,
public CefDisplayHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefDownloadHandler,
public CefKeyboardHandler,
public CefContextMenuHandler,
private CefDialogHandler {
public:
explicit FCHostHandler(bool use_views);
~FCHostHandler();
// Provide access to the single global instance of this object.
static FCHostHandler* GetInstance();
// CefClient methods:
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() override {
return this;
}
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override {
return this;
}
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() override { return this; }
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() override { return this; }
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override { return this; }
CefRefPtr< CefDialogHandler > GetDialogHandler() override { return this; }
bool OnFileDialog(CefRefPtr<CefBrowser> browser,
CefDialogHandler::FileDialogMode mode,
const CefString& title,
const CefString& default_file_path,
const std::vector<CefString>& accept_filters,
const std::vector<CefString>& accept_extensions,
const std::vector<CefString>& accept_descriptions,
CefRefPtr<CefFileDialogCallback> callback) override;
// CefDisplayHandler methods:
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) override;
virtual bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
cef_log_severity_t level,
const CefString& message,
const CefString& source,
int line) override;
// CefLifeSpanHandler methods:
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) override;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
// CefLoadHandler methods:
virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) override;
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override;
// CefDownloadHandler methods:
virtual bool OnBeforeDownload(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
const CefString& suggested_name,
CefRefPtr< CefBeforeDownloadCallback > callback) override;
// CefKeyboardHandler methods:
virtual bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
CefEventHandle os_event,
bool* is_keyboard_shortcut) override;
// CefContextMenuHandler methods:
virtual void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) override;
virtual bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags) override;
// Request that all existing browser windows close.
void CloseAllBrowsers(bool force_close);
bool IsClosing() const { return is_closing_; }
private:
// Platform-specific implementation.
void PlatformTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title);
// True if the application is using the Views framework.
const bool use_views_;
// List of existing browser windows. Only accessed on the CEF UI thread.
typedef std::list<CefRefPtr<CefBrowser>> BrowserList;
BrowserList browser_list_;
bool is_closing_;
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(FCHostHandler);
};
// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "fchost_handler.h"
#if defined(CEF_X11)
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#endif
#include "include/base/cef_logging.h"
#include "include/cef_browser.h"
#include <cstdlib>
#include <cstdio>
#include <filesystem>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
// #define TRACE
#ifdef TRACE
#include <iostream>
#endif
namespace {
std::string executeProcessAndReadStdOut(const std::string& command)
{
#ifdef TRACE
std::cerr << "Command: " << command << std::endl;
#endif
auto closer = [](FILE* fp) { ::pclose(fp); };
std::unique_ptr<FILE, decltype(closer)> f(::popen(command.c_str(), "r"), closer);
std::ostringstream output;
const int BUF_SIZE = 1024;
char buf[BUF_SIZE];
while(!std::feof(f.get())){
std::size_t read = std::fread(buf, 1, BUF_SIZE, f.get());
output.write(buf, static_cast<std::streamsize>(read));
}
std::string res = output.str();
return res.substr(0, res.size() - 1); // to clear out CR
}
std::string runKDialog(CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path,
const std::vector<CefString>& accept_filters)
{
std::ostringstream cmdLine;
cmdLine << "kdialog";
if (!title.empty()) {
cmdLine << " --title " << std::quoted(title.ToString());
}
#ifdef TRACE
std::cerr << "mode: " << std::hex << mode << std::dec << std::endl
<< "default_file_path: " << default_file_path << std::endl
<< "accept_filters: " << std::endl;
for (const auto& f: accept_filters) {
std::cerr << f.ToString() << std::endl;
}
#endif
switch (mode) {
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN_MULTIPLE:
cmdLine << " --multiple"; [[fallthrough]];
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN:
cmdLine << " --getopenfilename";
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_SAVE:
cmdLine << " --getsavefilename";
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN_FOLDER:
cmdLine << " --getexistingdirectory";
break;
default:
break; // TODO
}
const std::string dsp = default_file_path.ToString();
if (dsp.find('/') != std::string::npos) {
cmdLine << ' ' << std::quoted(dsp);
} else {
// TODO save last used directory and put it here instead of $HOME
cmdLine << ' ' << std::quoted(std::string(getenv("HOME")) + '/' + dsp);
}
if (accept_filters.size()) {
cmdLine << " \'";
for (const auto& f: accept_filters) {
const auto s = f.ToString();
cmdLine << " |" << s << " file(*" << s << ')';
}
cmdLine << '\'';
}
return executeProcessAndReadStdOut(cmdLine.str());
}
std::string runZenity(CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path,
const std::vector<CefString>& accept_filters)
{
std::ostringstream cmdLine;
cmdLine << "zenity --file-selection --confirm-overwrite";
switch (mode) {
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN_MULTIPLE:
cmdLine << " --multiple";
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN:
// this is the implicit default mode for zenity
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_SAVE:
cmdLine << " --save";
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN_FOLDER:
cmdLine << " --directory";
break;
default:
break; // TODO ?
}
const std::string dsp = default_file_path.ToString();
if (dsp.find('/') != std::string::npos) {
cmdLine << " --filename=" << std::quoted(dsp);
} else {
// TODO save last used directory and put it here instead of $HOME
cmdLine << " --filename=" << std::quoted(std::string(getenv("HOME")) + '/' + dsp);
}
for (const auto& f: accept_filters) {
const auto s = f.ToString();
cmdLine << " --file-filter=\"" << s << " file | *" << s << '"';
}
return executeProcessAndReadStdOut(cmdLine.str());
}
using DialogRunFunc = std::string (*)(CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path,
const std::vector<CefString>& accept_filters);
class DialogHelper {
public:
DialogHelper();
std::string operator()(CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path,
const std::vector<CefString>& accept_filters) const
{
return func_ ? func_(mode, title, default_file_path, accept_filters) : "";
}
private:
DialogRunFunc func_;
};
DialogHelper::DialogHelper()
{
// we will try to launch kdialog or zenity
std::string dialogExecutable;
// try to determine which environment we run inside
const char* desktop_env = getenv("XDG_CURRENT_DESKTOP");
std::string desktop = desktop_env == nullptr ? "" : desktop_env;
const auto checkExeExists = [](const char* name) {
int ec = ::system((std::string(name) + " --help > /dev/null").c_str());
return ec >= 0 && ec < 127;
};
if (desktop == "KDE") {
dialogExecutable = "kdialog";
} else if (desktop == "GNOME") {
dialogExecutable = "zenity";
} else {
// well, let's check executables
if (checkExeExists("zenity")) {
dialogExecutable = "zenity";
} else if (checkExeExists("kdialog")){
dialogExecutable = "kdialog";
}
}
#ifdef TRACE
std::cerr << "dialogExecutable: " << dialogExecutable << std::endl
<< "checkExeExists: " << checkExeExists(dialogExecutable.c_str()) << std::endl;
#endif
if (!dialogExecutable.empty() && checkExeExists(dialogExecutable.c_str())) {
if (dialogExecutable == "kdialog") {
func_ = &runKDialog;
} else if (dialogExecutable == "zenity") {
func_ = &runZenity;
} else {
func_ = nullptr;
}
}
}
}
void FCHostHandler::PlatformTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) {
std::string titleStr(title);
#if defined(CEF_X11)
// Retrieve the X11 display shared with Chromium.
::Display* display = cef_get_xdisplay();
DCHECK(display);
// Retrieve the X11 window handle for the browser.
::Window window = browser->GetHost()->GetWindowHandle();
if (window == kNullWindowHandle)
return;
// Retrieve the atoms required by the below XChangeProperty call.
const char* kAtoms[] = {"_NET_WM_NAME", "UTF8_STRING"};
Atom atoms[2];
int result =
XInternAtoms(display, const_cast<char**>(kAtoms), 2, false, atoms);
if (!result)
NOTREACHED();
// Set the window title.
XChangeProperty(display, window, atoms[0], atoms[1], 8, PropModeReplace,
reinterpret_cast<const unsigned char*>(titleStr.c_str()),
titleStr.size());
// TODO(erg): This is technically wrong. So XStoreName and friends expect
// this in Host Portable Character Encoding instead of UTF-8, which I believe
// is Compound Text. This shouldn't matter 90% of the time since this is the
// fallback to the UTF8 property above.
XStoreName(display, browser->GetHost()->GetWindowHandle(), titleStr.c_str());
#endif // defined(CEF_X11)
}
bool FCHostHandler::OnFileDialog(CefRefPtr<CefBrowser> /* browser */,
CefDialogHandler::FileDialogMode mode,
const CefString& title,
const CefString& default_file_path,
const std::vector<CefString>& accept_filters,
const std::vector<CefString>& /* accept_extensions */,
const std::vector<CefString>& /* accept_descriptions */,
CefRefPtr<CefFileDialogCallback> callback)
{
static DialogHelper helper;
std::string fn = helper(mode, title, default_file_path, accept_filters);
#ifdef TRACE
std::cerr << "fn: " << fn << std::endl;
#endif
if (fn.empty()) {
callback->Cancel();
return false;
}
std::vector<CefString> selected;
selected.push_back(fn);
callback->Continue(selected);
return true;
}
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "fchost_handler.h"
#include <windows.h>
#include <string>
#include "include/cef_browser.h"
#include "resource.h"
void FCHostHandler::PlatformTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) {
CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle();
static bool haveSetIcon = false;
if (!haveSetIcon)
{
HICON hicon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_FCHOST));
SendMessage(hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(hicon));
SendMessage(hwnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hicon));
DestroyIcon(hicon);
haveSetIcon = true;
}
SetWindowText(hwnd, std::wstring(title).c_str());
}
bool FCHostHandler::OnFileDialog(CefRefPtr<CefBrowser> /* browser */,
CefDialogHandler::FileDialogMode /* mode */,
const CefString& /* title */,
const CefString& /* default_file_path */,
const std::vector<CefString>& /* accept_filters */,
const std::vector<CefString>& /* accept_extensions */,
const std::vector<CefString>& /* accept_descriptions */,
CefRefPtr<CefFileDialogCallback> /* callback */)
{
return false; // to display the default dialog
}
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "fchost_app.h"
#if defined(CEF_X11)
#include <X11/Xlib.h>
#endif
#include "include/base/cef_logging.h"
#include "include/cef_command_line.h"
#include <filesystem>
std::filesystem::path FCHostApp::GetLocalStorePath()
{
return std::filesystem::path{getenv("HOME")} / ".local" / "share" / "FreeCities_Pregmod";
}
#if defined(CEF_X11)
namespace {
int XErrorHandlerImpl(Display* display, XErrorEvent* event) {
LOG(WARNING) << "X error received: "
<< "type " << event->type << ", "
<< "serial " << event->serial << ", "
<< "error_code " << static_cast<int>(event->error_code) << ", "
<< "request_code " << static_cast<int>(event->request_code)
<< ", "
<< "minor_code " << static_cast<int>(event->minor_code);
return 0;
}
int XIOErrorHandlerImpl(Display* display) {
return 0;
}
} // namespace
#endif // defined(CEF_X11)
// Entry point function for all processes.
int main(int argc, char* argv[]) {
// Provide CEF with command-line arguments.
CefMainArgs main_args(argc, argv);
// It will create the first browser instance in OnContextInitialized() after
// CEF has initialized.
CefRefPtr<FCHostApp> app(new FCHostApp);
// CEF applications have multiple sub-processes (render, plugin, GPU, etc)
// that share the same executable. This function checks the command-line and,
// if this is a sub-process, executes the appropriate logic.
int exit_code = CefExecuteProcess(main_args, app, nullptr);
if (exit_code >= 0) {
// The sub-process has completed so return here.
return exit_code;
}
#if defined(CEF_X11)
// Install xlib error handlers so that the application won't be terminated
// on non-fatal errors.
XSetErrorHandler(XErrorHandlerImpl);
XSetIOErrorHandler(XIOErrorHandlerImpl);
#endif
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromArgv(argc, argv);
return app->main(main_args, command_line.get());
}
#include "fchost_storage.h"
#include <algorithm>
#include <cstdio>
#include <memory>
#include <vector>
static_assert(CEF_STRING_TYPE_UTF16);
namespace fs = std::filesystem;
namespace {
struct closeFile {
void operator()(std::FILE* f) const noexcept
{
std::fclose(f);
}
};
}
CefRefPtr<CefV8Value> FCHostSessionStorage::keys() const
{
// holy hell this is awful. I hope Sugarcube doesn't actually USE this...
CefRefPtr<CefV8Value> ret = CefV8Value::CreateArray(static_cast<int>(storage.size()));
auto itr = storage.cbegin();
for (int i = 0; i < static_cast<int>(storage.size()); ++i, ++itr)
{
ret->SetValue(i, CefV8Value::CreateString(itr->first));
}
return ret;
}
/* This shouldn't happen, so don't waste time on it. Sugarcube really only writes simple alphanumeric keys.
static bool SanitizePath(std::wstring& inpath)
{
std::transform(inpath.begin(), inpath.end(), inpath.begin(), [](wchar_t c)
{
if (PathGetCharTypeW(c) != GCT_LFNCHAR)
return L'_';
else
return c;
});
}
*/
FCHostPersistentStorage::FCHostPersistentStorage(const std::filesystem::path& _path)
: path{_path}
{
ensure_folder_exists();
load();
}
void FCHostPersistentStorage::set(const CefString& key, CefRefPtr<CefV8Value> val)
{
base::set(key, val);
// only strings get persisted (should be OK, Sugarcube will serialize first)
if (val->IsString())
{
// we should probably be doing this async but TBT Sugarcube is the slow part, not the file IO
std::unique_ptr<std::FILE, closeFile> fh;
#if defined(OS_WIN)
fh.reset(_wfopen(get_filename(key).c_str(), L"wb"));
#else
fh.reset(std::fopen(get_filename(key).c_str(), "wb"));
#endif
CefString valStr = val->GetStringValue();
if (valStr.size() > 0) {
std::fwrite(valStr.c_str(), static_cast<size_t>(valStr.size() * sizeof(valStr.c_str()[0])), 1, fh.get());
}
}
}
bool FCHostPersistentStorage::remove(const CefString& key)
{
fs::remove(get_filename(key));
return base::remove(key);
}
void FCHostPersistentStorage::clear()
{
for (const auto& entry: fs::directory_iterator(path)) {
if (fs::is_regular_file(entry.path())) {
fs::remove_all(entry.path());
}
}
base::clear();
}
void FCHostPersistentStorage::load()
{
std::vector<char> readbuf;
std::unique_ptr<std::FILE, closeFile> fh;
for (const auto& entry: fs::directory_iterator(path)) {
if (fs::is_regular_file(entry.path())) {
const auto entrySize = fs::file_size(entry.path());
readbuf.resize(static_cast<std::size_t>(entrySize + 2)); // +1 char16
#if defined(OS_WIN)
fh.reset(_wfopen(entry.path().c_str(), L"rb"));
#else
fh.reset(std::fopen(entry.path().c_str(), "rb"));
#endif
if (std::fread(&readbuf[0], entrySize, 1, fh.get())) {
readbuf[entrySize + 1] = readbuf[entrySize] = 0; // null terminate
CefString val;
val.FromString16(static_cast<const char16_t*>(static_cast<const void*>(readbuf.data())));
auto sKey = entry.path().filename().native();
#if defined(OS_WIN)
// put the fucking colon back in it
const size_t loc = sKey.find(L'#', 0);
if (loc != std::wstring::npos) {
sKey.replace(loc, static_cast<size_t>(1), L":");
}
#endif
storage.emplace(sKey, CefV8Value::CreateString(val));
}
}
}
}
fs::path FCHostPersistentStorage::get_filename(const CefString& key) const
{
#if defined (OS_WIN)
std::wstring sKey = key.ToWString();
// some fool decided to use a fucking colon as a key separator for SC V3 saves...can't have that in a filename on windows...
const size_t loc = sKey.find(L':', 0);
if (loc != std::wstring::npos) {
sKey.replace(loc, static_cast<size_t>(1), L"#");
}
return path / sKey;
#else
return path / key.ToString();
#endif
}
void FCHostPersistentStorage::ensure_folder_exists() const
{
// ignore returned errors
fs::create_directories(path);
}
#pragma once
#include "include/cef_app.h" // probably excessive
#include <filesystem>
#include <map>
#include <string>
// simple memory-backed session storage
class FCHostSessionStorage
{
public:
virtual size_t size() const { return storage.size(); };
virtual CefRefPtr<CefV8Value> /* string array */ keys() const;
virtual bool has(const CefString& key) const { return (storage.find(key) != storage.cend()); };
virtual CefRefPtr<CefV8Value> get(const CefString& key) const
{
auto itr = storage.find(key);
if (itr == storage.cend())
return CefV8Value::CreateNull();
else
return itr->second;
};
virtual void set(const CefString& key, CefRefPtr<CefV8Value> val) { storage.insert_or_assign(key, val); };
virtual bool remove(const CefString& key) { return (storage.erase(key) > 0); };
virtual void clear() { storage.clear(); };
protected:
std::map<CefString, CefRefPtr<CefV8Value>> storage;
};
// memory-backed, disk-persistent local storage
class FCHostPersistentStorage : public FCHostSessionStorage
{
using base = FCHostSessionStorage;
public:
FCHostPersistentStorage(const std::filesystem::path& _path);
virtual void set(const CefString& key, CefRefPtr<CefV8Value> val) override;
virtual bool remove(const CefString& key) override;
virtual void clear() override;
private:
void load();
void ensure_folder_exists() const;
std::filesystem::path get_filename(const CefString& key) const;
std::filesystem::path path;
};