mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-13 07:17:28 +00:00
[common/client] platform: abstract runtime services
This commit is contained in:
182
client/platform/Windows/clipboard_files.c
Normal file
182
client/platform/Windows/clipboard_files.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "core/clipboard_files.h"
|
||||
#include "core/clipboard.h"
|
||||
|
||||
bool clipboardFiles_init(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void clipboardFiles_free(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool clipboardFiles_setLocal(const char * mime,
|
||||
const void * data, size_t size)
|
||||
{
|
||||
(void)mime;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return false;
|
||||
}
|
||||
|
||||
void clipboardFiles_clearLocal(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool clipboardFiles_getRemote(const char * mime,
|
||||
char ** data, size_t * size)
|
||||
{
|
||||
(void)mime;
|
||||
if (data)
|
||||
*data = NULL;
|
||||
if (size)
|
||||
*size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t clipboardFiles_remotePresentationAcquire(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool clipboardFiles_getRemotePresentation(uint64_t presentation,
|
||||
const char * mime, char ** data, size_t * size)
|
||||
{
|
||||
(void)presentation;
|
||||
(void)mime;
|
||||
if (data)
|
||||
*data = NULL;
|
||||
if (size)
|
||||
*size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void clipboardFiles_remotePresentationDelivered(uint64_t presentation)
|
||||
{
|
||||
(void)presentation;
|
||||
}
|
||||
|
||||
void clipboardFiles_remotePresentationRelease(uint64_t presentation)
|
||||
{
|
||||
(void)presentation;
|
||||
}
|
||||
|
||||
bool clipboardFiles_remoteReady(uint64_t dataset)
|
||||
{
|
||||
(void)dataset;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool clipboardFiles_remoteOffer(uint64_t dataset)
|
||||
{
|
||||
(void)dataset;
|
||||
return false;
|
||||
}
|
||||
|
||||
void clipboardFiles_remoteClear(void)
|
||||
{
|
||||
}
|
||||
|
||||
void clipboardFiles_providerUnavailable(void)
|
||||
{
|
||||
}
|
||||
|
||||
void clipboardFiles_remoteAcquired(uint64_t dataset,
|
||||
uint64_t acquisition, LG_ClipboardFileError error)
|
||||
{
|
||||
(void)dataset;
|
||||
(void)acquisition;
|
||||
(void)error;
|
||||
}
|
||||
|
||||
LG_ClipboardResult clipboardFiles_remoteDataBegin(
|
||||
const LG_ClipboardFileRequest * request, uint64_t sizeHint)
|
||||
{
|
||||
(void)request;
|
||||
(void)sizeHint;
|
||||
return LG_CLIPBOARD_RESULT_FAILED;
|
||||
}
|
||||
|
||||
LG_ClipboardResult clipboardFiles_remoteDataChunk(
|
||||
const LG_ClipboardFileRequest * request, uint64_t responseOffset,
|
||||
const void * data, size_t size)
|
||||
{
|
||||
(void)request;
|
||||
(void)responseOffset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return LG_CLIPBOARD_RESULT_FAILED;
|
||||
}
|
||||
|
||||
LG_ClipboardResult clipboardFiles_remoteDataEnd(
|
||||
const LG_ClipboardFileRequest * request, uint64_t finalSize)
|
||||
{
|
||||
(void)request;
|
||||
(void)finalSize;
|
||||
return LG_CLIPBOARD_RESULT_FAILED;
|
||||
}
|
||||
|
||||
void clipboardFiles_remoteCancel(uint64_t dataset,
|
||||
uint64_t request, LG_ClipboardFileError reason)
|
||||
{
|
||||
(void)dataset;
|
||||
(void)request;
|
||||
(void)reason;
|
||||
}
|
||||
|
||||
void clipboardFiles_localAcquire(uint64_t dataset,
|
||||
uint64_t acquisition)
|
||||
{
|
||||
clipboard_fileAcquired(dataset, acquisition,
|
||||
LG_CLIPBOARD_FILE_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
void clipboardFiles_localRelease(uint64_t dataset,
|
||||
uint64_t acquisition)
|
||||
{
|
||||
(void)dataset;
|
||||
(void)acquisition;
|
||||
}
|
||||
|
||||
void clipboardFiles_localRequest(
|
||||
const LG_ClipboardFileRequest * request)
|
||||
{
|
||||
if (!request)
|
||||
return;
|
||||
|
||||
clipboard_fileCancel(request->dataset, request->request,
|
||||
LG_CLIPBOARD_FILE_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
void clipboardFiles_localCancel(uint64_t dataset,
|
||||
uint64_t request, LG_ClipboardFileError reason)
|
||||
{
|
||||
(void)dataset;
|
||||
(void)request;
|
||||
(void)reason;
|
||||
}
|
||||
|
||||
void clipboardFiles_localReady(uint64_t request)
|
||||
{
|
||||
(void)request;
|
||||
}
|
||||
78
client/platform/Windows/entry.c
Normal file
78
client/platform/Windows/entry.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "platform/process.h"
|
||||
|
||||
#include "common/win32.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
static void freeArguments(int argc, char * argv[])
|
||||
{
|
||||
if (!argv)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < argc; ++i)
|
||||
free(argv[i]);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE instance, HINSTANCE previousInstance,
|
||||
LPSTR commandLine, int showCommand)
|
||||
{
|
||||
(void)instance;
|
||||
(void)previousInstance;
|
||||
(void)commandLine;
|
||||
(void)showCommand;
|
||||
|
||||
int argc = 0;
|
||||
wchar_t ** wideArgv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
if (!wideArgv || argc < 1)
|
||||
{
|
||||
if (wideArgv)
|
||||
LocalFree(wideArgv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
char ** argv = calloc((size_t)argc + 1U, sizeof(*argv));
|
||||
if (!argv)
|
||||
{
|
||||
LocalFree(wideArgv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
argv[i] = lgWideToUtf8(wideArgv[i]);
|
||||
if (!argv[i])
|
||||
{
|
||||
freeArguments(argc, argv);
|
||||
LocalFree(wideArgv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
LocalFree(wideArgv);
|
||||
|
||||
const int result = lgClientMain(argc, argv);
|
||||
freeArguments(argc, argv);
|
||||
return result;
|
||||
}
|
||||
459
client/platform/Windows/font.c
Normal file
459
client/platform/Windows/font.c
Normal file
@@ -0,0 +1,459 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define COBJMACROS
|
||||
#include <windows.h>
|
||||
#include <initguid.h>
|
||||
#include <dwrite.h>
|
||||
|
||||
#include "font_platform.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/win32.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct FontPlatform
|
||||
{
|
||||
IDWriteFactory * factory;
|
||||
IDWriteFontCollection * collection;
|
||||
IDWriteFont * primary;
|
||||
UINT32 primaryFamily;
|
||||
bool comInitialized;
|
||||
};
|
||||
|
||||
static bool font_platformGetFacePath(
|
||||
IDWriteFontFace * face, char ** path, int * index)
|
||||
{
|
||||
*path = NULL;
|
||||
*index = 0;
|
||||
|
||||
UINT32 fileCount = 0;
|
||||
HRESULT result = IDWriteFontFace_GetFiles(face, &fileCount, NULL);
|
||||
if (FAILED(result) || fileCount != 1)
|
||||
return false;
|
||||
|
||||
IDWriteFontFile * file = NULL;
|
||||
result = IDWriteFontFace_GetFiles(face, &fileCount, &file);
|
||||
if (FAILED(result) || !file)
|
||||
return false;
|
||||
|
||||
IDWriteFontFileLoader * loader = NULL;
|
||||
result = IDWriteFontFile_GetLoader(file, &loader);
|
||||
if (FAILED(result) || !loader)
|
||||
{
|
||||
IDWriteFontFile_Release(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
IDWriteLocalFontFileLoader * local = NULL;
|
||||
result = IDWriteFontFileLoader_QueryInterface(loader,
|
||||
&IID_IDWriteLocalFontFileLoader, (void **)&local);
|
||||
if (FAILED(result) || !local)
|
||||
{
|
||||
IDWriteFontFileLoader_Release(loader);
|
||||
IDWriteFontFile_Release(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
const void * key;
|
||||
UINT32 keySize;
|
||||
result = IDWriteFontFile_GetReferenceKey(file, &key, &keySize);
|
||||
if (FAILED(result))
|
||||
goto done;
|
||||
|
||||
UINT32 pathLength;
|
||||
result = IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(
|
||||
local, key, keySize, &pathLength);
|
||||
if (FAILED(result))
|
||||
goto done;
|
||||
|
||||
const UINT32 pathCapacity = pathLength + 1;
|
||||
if (!pathCapacity)
|
||||
goto done;
|
||||
|
||||
const size_t pathSize = (size_t)pathCapacity * sizeof(wchar_t);
|
||||
if (pathSize / sizeof(wchar_t) != pathCapacity)
|
||||
goto done;
|
||||
|
||||
wchar_t * widePath = malloc(pathSize);
|
||||
if (!widePath)
|
||||
goto done;
|
||||
|
||||
result = IDWriteLocalFontFileLoader_GetFilePathFromKey(
|
||||
local, key, keySize, widePath, pathCapacity);
|
||||
if (SUCCEEDED(result))
|
||||
*path = lgWideToUtf8(widePath);
|
||||
free(widePath);
|
||||
|
||||
const UINT32 faceIndex = IDWriteFontFace_GetIndex(face);
|
||||
if (!*path || faceIndex > INT_MAX)
|
||||
{
|
||||
free(*path);
|
||||
*path = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*index = (int)faceIndex;
|
||||
|
||||
done:
|
||||
IDWriteLocalFontFileLoader_Release(local);
|
||||
IDWriteFontFileLoader_Release(loader);
|
||||
IDWriteFontFile_Release(file);
|
||||
return *path != NULL;
|
||||
}
|
||||
|
||||
static bool font_platformGetFontPath(
|
||||
IDWriteFont * font, char ** path, int * index)
|
||||
{
|
||||
IDWriteFontFace * face = NULL;
|
||||
const HRESULT result = IDWriteFont_CreateFontFace(font, &face);
|
||||
if (FAILED(result) || !face)
|
||||
return false;
|
||||
|
||||
const bool success = font_platformGetFacePath(face, path, index);
|
||||
IDWriteFontFace_Release(face);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool font_platformGetFamilyFont(FontPlatform * platform,
|
||||
UINT32 familyIndex, IDWriteFont ** font)
|
||||
{
|
||||
*font = NULL;
|
||||
|
||||
IDWriteFontFamily * family = NULL;
|
||||
HRESULT result = IDWriteFontCollection_GetFontFamily(
|
||||
platform->collection, familyIndex, &family);
|
||||
if (FAILED(result) || !family)
|
||||
return false;
|
||||
|
||||
result = IDWriteFontFamily_GetFirstMatchingFont(family,
|
||||
DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STRETCH_NORMAL,
|
||||
DWRITE_FONT_STYLE_NORMAL, font);
|
||||
IDWriteFontFamily_Release(family);
|
||||
return SUCCEEDED(result) && *font;
|
||||
}
|
||||
|
||||
static bool font_platformFindFamily(FontPlatform * platform,
|
||||
const wchar_t * name, UINT32 * familyIndex)
|
||||
{
|
||||
BOOL exists = FALSE;
|
||||
const HRESULT result = IDWriteFontCollection_FindFamilyName(
|
||||
platform->collection, name, familyIndex, &exists);
|
||||
return SUCCEEDED(result) && exists;
|
||||
}
|
||||
|
||||
static bool font_platformAddFont(IDWriteFont * font,
|
||||
uint32_t * remaining, size_t * remainingCount,
|
||||
FontPlatformAddFaceFn addFace, void * opaque)
|
||||
{
|
||||
if (!*remainingCount)
|
||||
return true;
|
||||
|
||||
if (*remainingCount > UINT32_MAX ||
|
||||
*remainingCount > SIZE_MAX / sizeof(uint16_t) ||
|
||||
*remainingCount > SIZE_MAX / sizeof(uint32_t))
|
||||
return false;
|
||||
|
||||
IDWriteFontFace * face = NULL;
|
||||
HRESULT result = IDWriteFont_CreateFontFace(font, &face);
|
||||
if (FAILED(result) || !face)
|
||||
return true;
|
||||
|
||||
uint16_t * indices = malloc(*remainingCount * sizeof(*indices));
|
||||
uint32_t * covered = malloc(*remainingCount * sizeof(*covered));
|
||||
if (!indices || !covered)
|
||||
{
|
||||
free(indices);
|
||||
free(covered);
|
||||
IDWriteFontFace_Release(face);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = IDWriteFontFace_GetGlyphIndices(face, remaining,
|
||||
(UINT32)*remainingCount, indices);
|
||||
if (FAILED(result))
|
||||
{
|
||||
free(indices);
|
||||
free(covered);
|
||||
IDWriteFontFace_Release(face);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t coveredCount = 0;
|
||||
for (size_t i = 0; i < *remainingCount; ++i)
|
||||
if (indices[i])
|
||||
covered[coveredCount++] = remaining[i];
|
||||
free(indices);
|
||||
|
||||
if (!coveredCount)
|
||||
{
|
||||
free(covered);
|
||||
IDWriteFontFace_Release(face);
|
||||
return true;
|
||||
}
|
||||
|
||||
char * path;
|
||||
int index;
|
||||
if (!font_platformGetFacePath(face, &path, &index))
|
||||
{
|
||||
free(covered);
|
||||
IDWriteFontFace_Release(face);
|
||||
return true;
|
||||
}
|
||||
|
||||
IDWriteFontFace_Release(face);
|
||||
const FontPlatformFaceResult faceResult = addFace(
|
||||
opaque, path, index, covered, coveredCount);
|
||||
free(path);
|
||||
if (faceResult == FONT_PLATFORM_FACE_ERROR)
|
||||
{
|
||||
free(covered);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (faceResult == FONT_PLATFORM_FACE_ACCEPT)
|
||||
{
|
||||
size_t src = 0;
|
||||
size_t dst = 0;
|
||||
size_t coveredAt = 0;
|
||||
|
||||
while (src < *remainingCount)
|
||||
{
|
||||
if (coveredAt < coveredCount &&
|
||||
remaining[src] == covered[coveredAt])
|
||||
{
|
||||
++src;
|
||||
++coveredAt;
|
||||
continue;
|
||||
}
|
||||
|
||||
remaining[dst++] = remaining[src++];
|
||||
}
|
||||
|
||||
*remainingCount = dst;
|
||||
}
|
||||
|
||||
free(covered);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool font_platformInit(FontPlatform ** platform)
|
||||
{
|
||||
if (!platform)
|
||||
return false;
|
||||
|
||||
*platform = NULL;
|
||||
|
||||
FontPlatform * state = calloc(1, sizeof(*state));
|
||||
if (!state)
|
||||
return false;
|
||||
|
||||
HRESULT result = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
if (SUCCEEDED(result))
|
||||
state->comInitialized = true;
|
||||
else if (result != RPC_E_CHANGED_MODE)
|
||||
{
|
||||
DEBUG_ERROR("CoInitializeEx failed: 0x%08lx", (unsigned long)result);
|
||||
free(state);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
|
||||
&IID_IDWriteFactory, (IUnknown **)&state->factory);
|
||||
if (FAILED(result) || !state->factory)
|
||||
{
|
||||
DEBUG_ERROR("DWriteCreateFactory failed: 0x%08lx",
|
||||
(unsigned long)result);
|
||||
if (state->comInitialized)
|
||||
CoUninitialize();
|
||||
free(state);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = IDWriteFactory_GetSystemFontCollection(
|
||||
state->factory, &state->collection, FALSE);
|
||||
if (FAILED(result) || !state->collection)
|
||||
{
|
||||
DEBUG_ERROR("GetSystemFontCollection failed: 0x%08lx",
|
||||
(unsigned long)result);
|
||||
IDWriteFactory_Release(state->factory);
|
||||
if (state->comInitialized)
|
||||
CoUninitialize();
|
||||
free(state);
|
||||
return false;
|
||||
}
|
||||
|
||||
*platform = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
void font_platformFree(FontPlatform * platform)
|
||||
{
|
||||
if (!platform)
|
||||
return;
|
||||
|
||||
if (platform->primary)
|
||||
IDWriteFont_Release(platform->primary);
|
||||
if (platform->collection)
|
||||
IDWriteFontCollection_Release(platform->collection);
|
||||
if (platform->factory)
|
||||
IDWriteFactory_Release(platform->factory);
|
||||
if (platform->comInitialized)
|
||||
CoUninitialize();
|
||||
|
||||
free(platform);
|
||||
}
|
||||
|
||||
char * font_platformSelect(FontPlatform * platform, const char * fontName)
|
||||
{
|
||||
if (!platform || !fontName)
|
||||
return NULL;
|
||||
|
||||
const size_t familyLength = strcspn(fontName, ":");
|
||||
if (!familyLength || familyLength == SIZE_MAX)
|
||||
return NULL;
|
||||
|
||||
char * familyName = malloc(familyLength + 1);
|
||||
if (!familyName)
|
||||
return NULL;
|
||||
memcpy(familyName, fontName, familyLength);
|
||||
familyName[familyLength] = '\0';
|
||||
|
||||
wchar_t * wideName = lgUtf8ToWide(familyName);
|
||||
free(familyName);
|
||||
if (!wideName)
|
||||
return NULL;
|
||||
|
||||
static const wchar_t * fallbackNames[] =
|
||||
{
|
||||
L"Consolas",
|
||||
L"Segoe UI",
|
||||
};
|
||||
|
||||
IDWriteFont * selected = NULL;
|
||||
UINT32 selectedFamily = 0;
|
||||
char * selectedPath = NULL;
|
||||
int selectedIndex;
|
||||
|
||||
UINT32 familyIndex;
|
||||
if (font_platformFindFamily(platform, wideName, &familyIndex) &&
|
||||
font_platformGetFamilyFont(platform, familyIndex, &selected) &&
|
||||
font_platformGetFontPath(selected, &selectedPath, &selectedIndex))
|
||||
selectedFamily = familyIndex;
|
||||
else
|
||||
{
|
||||
if (selected)
|
||||
{
|
||||
IDWriteFont_Release(selected);
|
||||
selected = NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0;
|
||||
i < sizeof(fallbackNames) / sizeof(fallbackNames[0]); ++i)
|
||||
{
|
||||
if (!font_platformFindFamily(
|
||||
platform, fallbackNames[i], &familyIndex) ||
|
||||
!font_platformGetFamilyFont(platform, familyIndex, &selected) ||
|
||||
!font_platformGetFontPath(selected, &selectedPath, &selectedIndex))
|
||||
{
|
||||
if (selected)
|
||||
{
|
||||
IDWriteFont_Release(selected);
|
||||
selected = NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
selectedFamily = familyIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!selected &&
|
||||
IDWriteFontCollection_GetFontFamilyCount(platform->collection) &&
|
||||
font_platformGetFamilyFont(platform, 0, &selected) &&
|
||||
font_platformGetFontPath(selected, &selectedPath, &selectedIndex))
|
||||
selectedFamily = 0;
|
||||
}
|
||||
|
||||
free(wideName);
|
||||
if (!selected || !selectedPath)
|
||||
{
|
||||
if (selected)
|
||||
IDWriteFont_Release(selected);
|
||||
DEBUG_ERROR("Failed to locate the requested font: %s", fontName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (platform->primary)
|
||||
IDWriteFont_Release(platform->primary);
|
||||
platform->primary = selected;
|
||||
platform->primaryFamily = selectedFamily;
|
||||
return selectedPath;
|
||||
}
|
||||
|
||||
bool font_platformResolve(FontPlatform * platform,
|
||||
const uint32_t * glyphs, size_t glyphCount,
|
||||
FontPlatformAddFaceFn addFace, void * opaque, size_t * unresolved)
|
||||
{
|
||||
if (!platform || !platform->primary || (!glyphs && glyphCount) ||
|
||||
!addFace || !unresolved ||
|
||||
glyphCount > SIZE_MAX / sizeof(*glyphs))
|
||||
return false;
|
||||
|
||||
uint32_t * remaining = malloc(glyphCount * sizeof(*remaining));
|
||||
if (!remaining && glyphCount)
|
||||
return false;
|
||||
if (glyphCount)
|
||||
memcpy(remaining, glyphs, glyphCount * sizeof(*remaining));
|
||||
|
||||
size_t remainingCount = glyphCount;
|
||||
if (!font_platformAddFont(platform->primary, remaining,
|
||||
&remainingCount, addFace, opaque))
|
||||
goto fail;
|
||||
|
||||
const UINT32 familyCount = IDWriteFontCollection_GetFontFamilyCount(
|
||||
platform->collection);
|
||||
for (UINT32 i = 0; i < familyCount && remainingCount; ++i)
|
||||
{
|
||||
if (i == platform->primaryFamily)
|
||||
continue;
|
||||
|
||||
IDWriteFont * font = NULL;
|
||||
if (!font_platformGetFamilyFont(platform, i, &font))
|
||||
continue;
|
||||
|
||||
const bool success = font_platformAddFont(
|
||||
font, remaining, &remainingCount, addFace, opaque);
|
||||
IDWriteFont_Release(font);
|
||||
if (!success)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*unresolved = remainingCount;
|
||||
free(remaining);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
free(remaining);
|
||||
return false;
|
||||
}
|
||||
59
client/platform/Windows/input.c
Normal file
59
client/platform/Windows/input.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "platform/input.h"
|
||||
|
||||
void inputPlatformEarlyInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool inputPlatformStart(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void inputPlatformStop(void)
|
||||
{
|
||||
}
|
||||
|
||||
void inputPlatformFree(void)
|
||||
{
|
||||
}
|
||||
|
||||
void inputPlatformSetGrab(bool keyboard, bool pointer)
|
||||
{
|
||||
(void)keyboard;
|
||||
(void)pointer;
|
||||
}
|
||||
|
||||
bool inputPlatformIsKeyboardExclusive(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool inputPlatformIsPointerExclusive(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LG_DSEventSource inputPlatformGetEventSource(void)
|
||||
{
|
||||
return (LG_DSEventSource) { 0 };
|
||||
}
|
||||
130
client/platform/Windows/process.c
Normal file
130
client/platform/Windows/process.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "platform/process.h"
|
||||
|
||||
#include "common/win32.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
struct ProcessState
|
||||
{
|
||||
LG_ProcessStopHandler handler;
|
||||
void * opaque;
|
||||
bool installed;
|
||||
};
|
||||
|
||||
static struct ProcessState process;
|
||||
|
||||
static char * duplicateString(const char * value)
|
||||
{
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
const size_t length = strlen(value) + 1U;
|
||||
char * result = malloc(length);
|
||||
if (result)
|
||||
memcpy(result, value, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL WINAPI consoleHandler(DWORD type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
if (process.handler && process.handler(process.opaque))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
enum LG_ProcessPrivilege lgProcessGetPrivilege(void)
|
||||
{
|
||||
return LG_PROCESS_PRIVILEGE_NORMAL;
|
||||
}
|
||||
|
||||
char * lgProcessGetExecutablePath(const char * argv0)
|
||||
{
|
||||
DWORD capacity = MAX_PATH;
|
||||
while (capacity <= UINT32_MAX / 2U)
|
||||
{
|
||||
wchar_t * path = malloc((size_t)capacity * sizeof(*path));
|
||||
if (!path)
|
||||
break;
|
||||
|
||||
const DWORD length = GetModuleFileNameW(NULL, path, capacity);
|
||||
if (length > 0 && length < capacity)
|
||||
{
|
||||
path[length] = L'\0';
|
||||
char * result = lgWideToUtf8(path);
|
||||
free(path);
|
||||
if (result)
|
||||
return result;
|
||||
break;
|
||||
}
|
||||
|
||||
free(path);
|
||||
if (!length)
|
||||
break;
|
||||
capacity *= 2U;
|
||||
}
|
||||
|
||||
return duplicateString(argv0);
|
||||
}
|
||||
|
||||
bool lgProcessInstallStopHandler(LG_ProcessStopHandler handler, void * opaque)
|
||||
{
|
||||
if (!handler || process.installed)
|
||||
return false;
|
||||
|
||||
process.handler = handler;
|
||||
process.opaque = opaque;
|
||||
if (!SetConsoleCtrlHandler(consoleHandler, TRUE))
|
||||
{
|
||||
process.handler = NULL;
|
||||
process.opaque = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
process.installed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lgProcessRemoveStopHandler(void)
|
||||
{
|
||||
if (!process.installed)
|
||||
return;
|
||||
|
||||
SetConsoleCtrlHandler(consoleHandler, FALSE);
|
||||
process.handler = NULL;
|
||||
process.opaque = NULL;
|
||||
process.installed = false;
|
||||
}
|
||||
Reference in New Issue
Block a user