From 309b1b6ee70f196e6c2965f238f40a165862a4a7 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Tue, 25 May 2010 18:53:09 -0400 Subject: [PATCH 01/24] Adding GLTSF (somewhat based on SFML, no actual TSF code yet) --- EXCLUDE/GLTSF/GLTSF.sln | 20 ++ EXCLUDE/GLTSF/GLTSF.vcxproj | 97 ++++++++ EXCLUDE/GLTSF/GLTSF.vcxproj.filters | 45 ++++ EXCLUDE/GLTSF/include/App.hpp | 26 +++ EXCLUDE/GLTSF/include/Video_Mode.hpp | 30 +++ EXCLUDE/GLTSF/include/Window.hpp | 55 +++++ EXCLUDE/GLTSF/include/Window_Listener.hpp | 13 ++ EXCLUDE/GLTSF/src/App.cpp | 56 +++++ EXCLUDE/GLTSF/src/Main.cpp | 17 ++ EXCLUDE/GLTSF/src/Video_Mode.cpp | 100 ++++++++ EXCLUDE/GLTSF/src/Window.cpp | 263 ++++++++++++++++++++++ 11 files changed, 722 insertions(+) create mode 100644 EXCLUDE/GLTSF/GLTSF.sln create mode 100644 EXCLUDE/GLTSF/GLTSF.vcxproj create mode 100644 EXCLUDE/GLTSF/GLTSF.vcxproj.filters create mode 100644 EXCLUDE/GLTSF/include/App.hpp create mode 100644 EXCLUDE/GLTSF/include/Video_Mode.hpp create mode 100644 EXCLUDE/GLTSF/include/Window.hpp create mode 100644 EXCLUDE/GLTSF/include/Window_Listener.hpp create mode 100644 EXCLUDE/GLTSF/src/App.cpp create mode 100644 EXCLUDE/GLTSF/src/Main.cpp create mode 100644 EXCLUDE/GLTSF/src/Video_Mode.cpp create mode 100644 EXCLUDE/GLTSF/src/Window.cpp diff --git a/EXCLUDE/GLTSF/GLTSF.sln b/EXCLUDE/GLTSF/GLTSF.sln new file mode 100644 index 000000000..f69c11422 --- /dev/null +++ b/EXCLUDE/GLTSF/GLTSF.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GLTSF", "GLTSF.vcxproj", "{790D58BA-E5F6-4286-A9C6-0DC28779789D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {790D58BA-E5F6-4286-A9C6-0DC28779789D}.Debug|Win32.ActiveCfg = Debug|Win32 + {790D58BA-E5F6-4286-A9C6-0DC28779789D}.Debug|Win32.Build.0 = Debug|Win32 + {790D58BA-E5F6-4286-A9C6-0DC28779789D}.Release|Win32.ActiveCfg = Release|Win32 + {790D58BA-E5F6-4286-A9C6-0DC28779789D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/EXCLUDE/GLTSF/GLTSF.vcxproj b/EXCLUDE/GLTSF/GLTSF.vcxproj new file mode 100644 index 000000000..374e16c12 --- /dev/null +++ b/EXCLUDE/GLTSF/GLTSF.vcxproj @@ -0,0 +1,97 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {790D58BA-E5F6-4286-A9C6-0DC28779789D} + Win32Proj + GLTSF + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + $(SolutionDir)bin\ + obj\$(Configuration)\ + + + false + $(SolutionDir)bin\ + obj\$(Configuration)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + include;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + include;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EXCLUDE/GLTSF/GLTSF.vcxproj.filters b/EXCLUDE/GLTSF/GLTSF.vcxproj.filters new file mode 100644 index 000000000..04c10f6df --- /dev/null +++ b/EXCLUDE/GLTSF/GLTSF.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/EXCLUDE/GLTSF/include/App.hpp b/EXCLUDE/GLTSF/include/App.hpp new file mode 100644 index 000000000..658f73b81 --- /dev/null +++ b/EXCLUDE/GLTSF/include/App.hpp @@ -0,0 +1,26 @@ +#ifndef APP_HPP +#define APP_HPP + +#include "Window.hpp" + +class App : public Window_Listener +{ +public: + App(); + virtual ~App(); + + void Initialize(); + void Finalize(); + + void Run(); + + virtual void On_Close(); + virtual void On_Key_Down(int Key); + virtual void On_Key_Up(int Key); + +private: + Window my_Window; + bool my_Done; +}; + +#endif diff --git a/EXCLUDE/GLTSF/include/Video_Mode.hpp b/EXCLUDE/GLTSF/include/Video_Mode.hpp new file mode 100644 index 000000000..00a801400 --- /dev/null +++ b/EXCLUDE/GLTSF/include/Video_Mode.hpp @@ -0,0 +1,30 @@ +#ifndef VIDEO_MODE_HPP +#define VIDEO_MODE_HPP + +#include + +class Video_Mode +{ +public: + Video_Mode(); + Video_Mode(unsigned int The_Width, unsigned int The_Height, unsigned int The_Bits_Per_Pixel); + + static Video_Mode Get_Desktop_Mode(); + + static std::size_t Get_Mode_Count(); + static Video_Mode Get_Mode(std::size_t Index); + + bool Is_Valid() const; + + bool operator==(const Video_Mode &Mode) const; + bool operator!=(const Video_Mode &Mode) const; + + unsigned int Width; + unsigned int Height; + unsigned int Bits_Per_Pixel; + +private: + static void Initialize_Modes(); +}; + +#endif diff --git a/EXCLUDE/GLTSF/include/Window.hpp b/EXCLUDE/GLTSF/include/Window.hpp new file mode 100644 index 000000000..f07fd477a --- /dev/null +++ b/EXCLUDE/GLTSF/include/Window.hpp @@ -0,0 +1,55 @@ +#ifndef WINDOW_HPP +#define WINDOW_HPP + +#include + +#define WIN32_LEAN_AND_MEAN +#include + +#include "Video_Mode.hpp" +#include "Window_Listener.hpp" + +class Window +{ +public: + Window(); + ~Window(); + + void Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen); + void Finalize(); + + void Set_Listener(Window_Listener *Listener); + + void Show(); + void Hide(); + + void Update(); + void Display(); + +private: + static const wchar_t *Window_Class_Name; + + void Register_Class(); + void Unregister_Class(); + + void Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen); + void Destroy_Window(); + + void Create_Context(const Video_Mode &Mode); + void Destroy_Context(); + + void Switch_To_Fullscreen(const Video_Mode &Mode); + + LRESULT Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam); + + HWND my_Handle; + Video_Mode my_Video_Mode; + bool my_Fullscreen; + HDC my_Device_Context; + HGLRC my_GL_Context; + bool my_Class_Registered; + Window_Listener *my_Listener; +}; + +#endif diff --git a/EXCLUDE/GLTSF/include/Window_Listener.hpp b/EXCLUDE/GLTSF/include/Window_Listener.hpp new file mode 100644 index 000000000..52396f7e8 --- /dev/null +++ b/EXCLUDE/GLTSF/include/Window_Listener.hpp @@ -0,0 +1,13 @@ +#ifndef WINDOW_LISTENER_HPP +#define WINDOW_LISTENER_HPP + +class Window_Listener +{ +public: + virtual void On_Close(){} + + virtual void On_Key_Down(int Key){} + virtual void On_Key_Up(int Key){} +}; + +#endif diff --git a/EXCLUDE/GLTSF/src/App.cpp b/EXCLUDE/GLTSF/src/App.cpp new file mode 100644 index 000000000..ae8ca73a5 --- /dev/null +++ b/EXCLUDE/GLTSF/src/App.cpp @@ -0,0 +1,56 @@ +#include "App.hpp" + +App::App() : my_Done(false) +{ + +} + +App::~App() +{ + Finalize(); +} + +void App::Initialize() +{ + Finalize(); + + my_Window.Initialize(L"GLTSF", Video_Mode(800, 600, 32), false); + my_Window.Set_Listener(this); + my_Window.Show(); +} + +void App::Finalize() +{ + my_Window.Finalize(); +} + +void App::Run() +{ + Initialize(); + while (!my_Done) + { + my_Window.Update(); + my_Window.Display(); + } +} + +void App::On_Close() +{ + my_Done = true; + my_Window.Hide(); +} + +void App::On_Key_Down(int Key) +{ + switch (Key) + { + case VK_ESCAPE: + On_Close(); + break; + } +} + +void App::On_Key_Up(int Key) +{ + +} diff --git a/EXCLUDE/GLTSF/src/Main.cpp b/EXCLUDE/GLTSF/src/Main.cpp new file mode 100644 index 000000000..31febadbf --- /dev/null +++ b/EXCLUDE/GLTSF/src/Main.cpp @@ -0,0 +1,17 @@ +#include "App.hpp" +#include + +int main(int argc, char *argv[]) +{ + try + { + App theApp; + theApp.Run(); + } + catch (const std::exception& e) + { + printf("Error: %s\n", e.what()); + return 1; + } + return 0; +} diff --git a/EXCLUDE/GLTSF/src/Video_Mode.cpp b/EXCLUDE/GLTSF/src/Video_Mode.cpp new file mode 100644 index 000000000..177e8b956 --- /dev/null +++ b/EXCLUDE/GLTSF/src/Video_Mode.cpp @@ -0,0 +1,100 @@ +#include "Video_Mode.hpp" +#include +#include +#define WIN32_LEAN_AND_MEAN +#include + +namespace +{ + + typedef std::vector Video_Mode_List; + Video_Mode_List Supported_Modes; + + struct Compare_Modes + { + bool operator()(const Video_Mode &Mode_1, const Video_Mode &Mode_2) const + { + if (Mode_1.Bits_Per_Pixel > Mode_2.Bits_Per_Pixel) + return true; + else if (Mode_1.Bits_Per_Pixel < Mode_2.Bits_Per_Pixel) + return false; + else if (Mode_1.Width > Mode_2.Width) + return true; + else if (Mode_1.Width < Mode_2.Width) + return false; + else + return Mode_1.Height > Mode_2.Height; + } + }; + +} + +Video_Mode::Video_Mode() : Width(0), + Height(0), + Bits_Per_Pixel(0) +{ + +} + +Video_Mode::Video_Mode(unsigned int The_Width, unsigned int The_Height, unsigned int The_Bits_Per_Pixel) + : Width(The_Width), + Height(The_Height), + Bits_Per_Pixel(The_Bits_Per_Pixel) +{ + +} + +Video_Mode Video_Mode::Get_Desktop_Mode() +{ + DEVMODE Device_Mode = {0}; + Device_Mode.dmSize = sizeof(Device_Mode); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &Device_Mode); + return Video_Mode(Device_Mode.dmPelsWidth, Device_Mode.dmPelsHeight, Device_Mode.dmBitsPerPel); +} + +std::size_t Video_Mode::Get_Mode_Count() +{ + Initialize_Modes(); + return Supported_Modes.size(); +} + +Video_Mode Video_Mode::Get_Mode(std::size_t Index) +{ + Initialize_Modes(); + return Supported_Modes[Index]; +} + +bool Video_Mode::Is_Valid() const +{ + Initialize_Modes(); + return Supported_Modes.end() != std::find(Supported_Modes.begin(), Supported_Modes.end(), *this); +} + +bool Video_Mode::operator==(const Video_Mode &Mode) const +{ + return (Width == Mode.Width + && Height == Mode.Height + && Bits_Per_Pixel == Mode.Bits_Per_Pixel); +} + +bool Video_Mode::operator!=(const Video_Mode &Mode) const +{ + return !(*this == Mode); +} + +void Video_Mode::Initialize_Modes() +{ + static bool Initialized = false; + if (!Initialized) + { + DEVMODE Device_Mode = {0}; + Device_Mode.dmSize = sizeof(Device_Mode); + for (std::size_t i = 0; 0 != EnumDisplaySettings(NULL, i, &Device_Mode); ++i) + { + Video_Mode Mode(Device_Mode.dmPelsWidth, Device_Mode.dmPelsHeight, Device_Mode.dmBitsPerPel); + if (Supported_Modes.end() == std::find(Supported_Modes.begin(), Supported_Modes.end(), Mode)) + Supported_Modes.push_back(Mode); + } + std::sort(Supported_Modes.begin(), Supported_Modes.end(), Compare_Modes()); + } +} diff --git a/EXCLUDE/GLTSF/src/Window.cpp b/EXCLUDE/GLTSF/src/Window.cpp new file mode 100644 index 000000000..955693c05 --- /dev/null +++ b/EXCLUDE/GLTSF/src/Window.cpp @@ -0,0 +1,263 @@ +#include "Window.hpp" + +#pragma comment(lib, "opengl32.lib") + +const wchar_t *Window::Window_Class_Name = L"GLTSF"; + +Window::Window() : my_Handle(0), + my_Device_Context(0), + my_GL_Context(0), + my_Class_Registered(false), + my_Listener(0) +{ + +} + +Window::~Window() +{ + Finalize(); +} + +void Window::Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen) +{ + Finalize(); + + my_Video_Mode = Mode; + if (!my_Video_Mode.Is_Valid()) + throw std::runtime_error("Invalid video mode"); + + my_Fullscreen = Fullscreen; + Register_Class(); + Create_Window(Title, Mode, Fullscreen); +} + +void Window::Finalize() +{ + Destroy_Window(); + Unregister_Class(); +} + +void Window::Set_Listener(Window_Listener *Listener) +{ + my_Listener = Listener; +} + +void Window::Register_Class() +{ + WNDCLASSEXW Window_Class = {0}; + Window_Class.cbSize = sizeof(Window_Class); + Window_Class.style = 0; + Window_Class.lpfnWndProc = &Window::Window_Procedure; + Window_Class.cbClsExtra = 0; + Window_Class.cbWndExtra = 0; + Window_Class.hInstance = GetModuleHandle(NULL); + Window_Class.hIcon = NULL; + Window_Class.hCursor = NULL; + Window_Class.hbrBackground = NULL; + Window_Class.lpszMenuName = NULL; + Window_Class.lpszClassName = Window_Class_Name; + Window_Class.hIconSm = NULL; + if (0 == RegisterClassExW(&Window_Class)) + throw std::runtime_error("Failed to register window class"); + + my_Class_Registered = true; +} + +void Window::Unregister_Class() +{ + if (my_Class_Registered) + { + if (0 == UnregisterClassW(Window_Class_Name, GetModuleHandle(NULL))) + printf("Warning: Failed to unregister window class\n"); + + my_Class_Registered = false; + } +} + +void Window::Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen) +{ + HDC Screen_DC = GetDC(NULL); + int Left = (GetDeviceCaps(Screen_DC, HORZRES) - my_Video_Mode.Width) / 2; + int Top = (GetDeviceCaps(Screen_DC, VERTRES) - my_Video_Mode.Height) / 2; + int Width = my_Video_Mode.Width; + int Height = my_Video_Mode.Height; + ReleaseDC(NULL, Screen_DC); + + DWORD Style = WS_OVERLAPPEDWINDOW; + if (!my_Fullscreen) + { + RECT Rect = {0, 0, Width, Height}; + AdjustWindowRect(&Rect, Style, false); + Width = Rect.right - Rect.left; + Height = Rect.bottom - Rect.top; + } + my_Handle = CreateWindowW(Window_Class_Name, Title.c_str(), Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this); + if (!my_Handle) + throw std::runtime_error("Failed to create window"); + + if (Fullscreen) + Switch_To_Fullscreen(Mode); + + Create_Context(Mode); + + RECT Rect = {0}; + GetClientRect(my_Handle, &Rect); + //TODO: ... +} + +void Window::Destroy_Window() +{ + Destroy_Context(); + if (my_Handle) + { + DestroyWindow(my_Handle); + my_Handle = 0; + + if (my_Fullscreen) + ChangeDisplaySettings(NULL, 0); + } +} + +void Window::Create_Context(const Video_Mode &Mode) +{ + my_Device_Context = GetDC(my_Handle); + if (!my_Device_Context) + throw std::runtime_error("Failed to get device context"); + + PIXELFORMATDESCRIPTOR Pixel_Descriptor = {0}; + Pixel_Descriptor.nSize = sizeof(Pixel_Descriptor); + Pixel_Descriptor.nVersion = 1; + Pixel_Descriptor.iLayerType = PFD_MAIN_PLANE; + Pixel_Descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + Pixel_Descriptor.iPixelType = PFD_TYPE_RGBA; + Pixel_Descriptor.cColorBits = static_cast(Mode.Bits_Per_Pixel); + Pixel_Descriptor.cDepthBits = 24; + Pixel_Descriptor.cStencilBits = 8; + Pixel_Descriptor.cAlphaBits = Mode.Bits_Per_Pixel == 32 ? 8 : 0; + + int Best_Format = ChoosePixelFormat(my_Device_Context, &Pixel_Descriptor); + if (0 == Best_Format) + throw std::runtime_error("Failed to find suitable pixel format"); + + PIXELFORMATDESCRIPTOR Actual_Format = {0}; + Actual_Format.nSize = sizeof(Actual_Format); + Actual_Format.nVersion = 1; + DescribePixelFormat(my_Device_Context, Best_Format, sizeof(Actual_Format), &Actual_Format); + if (!SetPixelFormat(my_Device_Context, Best_Format, &Actual_Format)) + throw std::runtime_error("Failed to set device pixel format"); + + my_GL_Context = wglCreateContext(my_Device_Context); + if (!my_GL_Context) + throw std::runtime_error("Failed to create OpenGL context"); + + wglMakeCurrent(my_Device_Context, my_GL_Context); +} + +void Window::Destroy_Context() +{ + if (my_GL_Context) + { + wglDeleteContext(my_GL_Context); + my_GL_Context = 0; + } + if (my_Device_Context) + { + ReleaseDC(my_Handle, my_Device_Context); + my_Device_Context = 0; + } +} + +void Window::Switch_To_Fullscreen(const Video_Mode &Mode) +{ + DEVMODE Device_Mode = {0}; + Device_Mode.dmSize = sizeof(Device_Mode); + Device_Mode.dmPelsWidth = Mode.Width; + Device_Mode.dmPelsHeight = Mode.Height; + Device_Mode.dmBitsPerPel = Mode.Bits_Per_Pixel; + Device_Mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + + if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&Device_Mode, CDS_FULLSCREEN)) + throw std::runtime_error("Failed to change to fullscreen mode"); + + SetWindowLong(my_Handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + SetWindowLong(my_Handle, GWL_EXSTYLE, WS_EX_APPWINDOW); + + SetWindowPos(my_Handle, HWND_TOP, 0, 0, Mode.Width, Mode.Height, SWP_FRAMECHANGED); +} + +LRESULT CALLBACK Window::Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam) +{ + switch (Message) + { + case WM_CREATE: + { + LONG This = reinterpret_cast(reinterpret_cast(lParam)->lpCreateParams); + SetWindowLongPtr(Handle, GWLP_USERDATA, This); + return 0; + } + break; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + break; + default: + { + Window* Win = reinterpret_cast(GetWindowLongPtr(Handle, GWLP_USERDATA)); + if (Win) + return Win->Handle_Message(Handle, Message, wParam, lParam); + } + break; + } + return DefWindowProcW(Handle, Message, wParam, lParam); +} + +#define Call_Listener(x)\ + if (my_Listener) my_Listener->x + +LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam) +{ + switch (Message) + { + case WM_CLOSE: + Call_Listener(On_Close()); + break; + case WM_KEYDOWN: + Call_Listener(On_Key_Down(wParam)); + break; + case WM_KEYUP: + Call_Listener(On_Key_Up(wParam)); + break; + default: + return DefWindowProcW(Handle, Message, wParam, lParam); + break; + } + return 0; +} + +void Window::Show() +{ + if (my_Handle) + ShowWindow(my_Handle, SW_SHOW); +} + +void Window::Hide() +{ + if (my_Handle) + ShowWindow(my_Handle, SW_HIDE); +} + +void Window::Update() +{ + MSG Message = {0}; + while (PeekMessageW(&Message, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&Message); + DispatchMessageW(&Message); + } +} + +void Window::Display() +{ + if (my_Device_Context && my_GL_Context) + SwapBuffers(my_Device_Context); +} From 7327c7a12e2a6f209aa58feb7c8dec805c0adc67 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Thu, 27 May 2010 20:47:52 -0400 Subject: [PATCH 02/24] Adding some initial TSF code --- EXCLUDE/GLTSF/GLTSF.vcxproj | 2 ++ EXCLUDE/GLTSF/GLTSF.vcxproj.filters | 6 ++++ EXCLUDE/GLTSF/include/TSF.hpp | 44 +++++++++++++++++++++++++++++ EXCLUDE/GLTSF/src/TSF.cpp | 1 + 4 files changed, 53 insertions(+) create mode 100644 EXCLUDE/GLTSF/include/TSF.hpp create mode 100644 EXCLUDE/GLTSF/src/TSF.cpp diff --git a/EXCLUDE/GLTSF/GLTSF.vcxproj b/EXCLUDE/GLTSF/GLTSF.vcxproj index 374e16c12..bc2928c22 100644 --- a/EXCLUDE/GLTSF/GLTSF.vcxproj +++ b/EXCLUDE/GLTSF/GLTSF.vcxproj @@ -81,6 +81,7 @@ + @@ -88,6 +89,7 @@ + diff --git a/EXCLUDE/GLTSF/GLTSF.vcxproj.filters b/EXCLUDE/GLTSF/GLTSF.vcxproj.filters index 04c10f6df..acab9f8e0 100644 --- a/EXCLUDE/GLTSF/GLTSF.vcxproj.filters +++ b/EXCLUDE/GLTSF/GLTSF.vcxproj.filters @@ -27,6 +27,9 @@ Header Files + + Header Files + @@ -41,5 +44,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/EXCLUDE/GLTSF/include/TSF.hpp b/EXCLUDE/GLTSF/include/TSF.hpp new file mode 100644 index 000000000..5453b9acd --- /dev/null +++ b/EXCLUDE/GLTSF/include/TSF.hpp @@ -0,0 +1,44 @@ +#ifndef TSF_HPP +#define TSF_HPP + +#include + +class TSF +{ +public: + +protected: + class UI_Sink : public ITfUIElementSink, public ITfInputProcessorProfileActivationSink + { + public: + UI_Sink(); + ~UI_Sink(); + + // IUnknown + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj); + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP_(ULONG) Release(void); + + // ITfUIElementSink + STDMETHODIMP BeginUIElement(DWORD dwUIElementId, BOOL *pbShow); + STDMETHODIMP UpdateUIElement(DWORD dwUIElementId); + STDMETHODIMP EndUIElement(DWORD dwUIElementId); + + // ITfInputProcessorProfileActivationSink + STDMETHODIMP OnActivated(DWORD dwProfileType, LANGID langid, + REFCLSID clsid, REFGUID catid, + REFGUID guidProfile, HKL hkl, + DWORD dwFlags); + + // ITfCompartmentEventSink + STDMETHODIMP OnChange(REFGUID rguid); + + private: + LONG my_Reference_Count; + }; + +private: + +}; + +#endif diff --git a/EXCLUDE/GLTSF/src/TSF.cpp b/EXCLUDE/GLTSF/src/TSF.cpp new file mode 100644 index 000000000..f21d968cd --- /dev/null +++ b/EXCLUDE/GLTSF/src/TSF.cpp @@ -0,0 +1 @@ +#include "TSF.hpp" From e0a87edc6ea750dfc90a6fa097b019bf415df467 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Sun, 30 May 2010 15:48:16 -0400 Subject: [PATCH 03/24] Implementing base parts of TSF --- EXCLUDE/GLTSF/include/TSF.hpp | 13 ++++ EXCLUDE/GLTSF/src/TSF.cpp | 139 ++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/EXCLUDE/GLTSF/include/TSF.hpp b/EXCLUDE/GLTSF/include/TSF.hpp index 5453b9acd..c37f4a4be 100644 --- a/EXCLUDE/GLTSF/include/TSF.hpp +++ b/EXCLUDE/GLTSF/include/TSF.hpp @@ -2,6 +2,7 @@ #define TSF_HPP #include +#include class TSF { @@ -37,8 +38,20 @@ class TSF LONG my_Reference_Count; }; + TSF(); + ~TSF(); + + void Initialize(); + void Finalize(); + private: + bool my_COM_Initialized; + + CComPtr my_Thread_Manager; + UI_Sink *my_UI_Sink; + DWORD my_UI_Element_Sink_Cookie; + DWORD my_IPPA_Sink_Cookie; }; #endif diff --git a/EXCLUDE/GLTSF/src/TSF.cpp b/EXCLUDE/GLTSF/src/TSF.cpp index f21d968cd..2f2df17c5 100644 --- a/EXCLUDE/GLTSF/src/TSF.cpp +++ b/EXCLUDE/GLTSF/src/TSF.cpp @@ -1 +1,140 @@ #include "TSF.hpp" +#include + +TSF::TSF() : my_COM_Initialized(false), + my_UI_Sink(0), + my_UI_Element_Sink_Cookie(TF_INVALID_COOKIE), + my_IPPA_Sink_Cookie(TF_INVALID_COOKIE) +{ + +} + +TSF::~TSF() +{ + Finalize(); +} + +void TSF::Initialize() +{ + Finalize(); + + if (S_OK != CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)) + throw std::runtime_error("Failed to initialize COM"); + + my_COM_Initialized = true; + if (S_OK != CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, __uuidof(ITfThreadMgrEx), (void **)&my_Thread_Manager)) + throw std::runtime_error("Failed to create ITfThreadMgrEx instance"); + + TfClientId Client_Id = 0; + if (FAILED(my_Thread_Manager->ActivateEx(&Client_Id, TF_TMAE_UIELEMENTENABLEDONLY))) + throw std::runtime_error("ITfThreadMgrEx::ActivateEx failed"); + + my_UI_Sink = new UI_Sink(); + ITfSource *Source = NULL; + if (FAILED(my_Thread_Manager->QueryInterface(__uuidof(ITfSource), (void **)&Source))) + throw std::runtime_error("QueryInterface failed"); + + if (FAILED(Source->AdviseSink(__uuidof(ITfUIElementSink), (ITfUIElementSink *)my_UI_Sink, &my_UI_Element_Sink_Cookie))) + throw std::runtime_error("AdviseSink failed"); + + if (FAILED(Source->AdviseSink(__uuidof(ITfInputProcessorProfileActivationSink), (ITfInputProcessorProfileActivationSink *)my_UI_Sink, &my_IPPA_Sink_Cookie))) + throw std::runtime_error("AdviseSink failed"); +} + +void TSF::Finalize() +{ + if (my_UI_Sink) + { + ITfSource *Source = NULL; + if (SUCCEEDED(my_Thread_Manager->QueryInterface(__uuidof(ITfSource), (void **)&Source))) + { + Source->UnadviseSink(my_IPPA_Sink_Cookie); + Source->UnadviseSink(my_UI_Element_Sink_Cookie); + Source->Release(); + } + if (my_Thread_Manager) + my_Thread_Manager->Deactivate(); + + my_UI_Sink->Release(); + delete my_UI_Sink; + my_UI_Sink = NULL; + } + my_Thread_Manager = NULL; + if (my_COM_Initialized) + { + CoUninitialize(); + my_COM_Initialized = false; + } +} + +TSF::UI_Sink::UI_Sink() +{ + my_Reference_Count = 1; +} + +TSF::UI_Sink::~UI_Sink() +{ + +} + +STDMETHODIMP TSF::UI_Sink::QueryInterface(REFIID riid, void **ppvObj) +{ + if (NULL == ppvObj) + return E_INVALIDARG; + + *ppvObj = NULL; + if (IsEqualIID(riid, IID_IUnknown)) + *ppvObj = reinterpret_cast(this); + else if (IsEqualIID(riid, __uuidof(ITfUIElementSink))) + *ppvObj = reinterpret_cast(this); + else if (IsEqualIID(riid, __uuidof(ITfInputProcessorProfileActivationSink))) + *ppvObj = reinterpret_cast(this); + else if (IsEqualIID(riid, __uuidof(ITfCompartmentEventSink))) + *ppvObj = reinterpret_cast(this); + + if (*ppvObj) + { + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +ULONG TSF::UI_Sink::AddRef(void) +{ + return ++my_Reference_Count; +} + +ULONG TSF::UI_Sink::Release(void) +{ + LONG Count = --my_Reference_Count; + if (0 == Count) + delete this; + + return Count; +} + +STDMETHODIMP TSF::UI_Sink::BeginUIElement(DWORD dwUIElementId, BOOL *pbShow) +{ + return S_OK; +} + +STDMETHODIMP TSF::UI_Sink::UpdateUIElement(DWORD dwUIElementId) +{ + return S_OK; +} + +STDMETHODIMP TSF::UI_Sink::EndUIElement(DWORD dwUIElementId) +{ + return S_OK; +} + +STDMETHODIMP TSF::UI_Sink::OnActivated(DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags) +{ + return S_OK; +} + +STDMETHODIMP TSF::UI_Sink::OnChange(REFGUID rguid) +{ + return S_OK; +} From 683b09d3afafe0de8bc066460e06e83bfd9c6784 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Tue, 8 Jun 2010 05:22:49 -0400 Subject: [PATCH 04/24] Change SDL to not use DefWindowProc as the window class' window procedure. For some reason, having lpfnWndProc=DefWindowProc during window class registration causes IME input to not work in windows. With this small change, IME input should now work in SDL windows but not in fullscreen mode. --- src/video/win32/SDL_win32events.c | 2 +- src/video/win32/SDL_win32window.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/win32/SDL_win32events.c b/src/video/win32/SDL_win32events.c index df4a3b722..6d30beee8 100644 --- a/src/video/win32/SDL_win32events.c +++ b/src/video/win32/SDL_win32events.c @@ -703,7 +703,7 @@ SDL_RegisterApp(char *name, Uint32 style, void *hInst) class.hbrBackground = NULL; class.hInstance = SDL_Instance; class.style = SDL_Appstyle; - class.lpfnWndProc = DefWindowProc; + class.lpfnWndProc = WIN_WindowProc; class.cbWndExtra = 0; class.cbClsExtra = 0; if (!RegisterClass(&class)) { diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index f69d38573..d69ba6a63 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -112,7 +112,7 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created) /* Set up the window proc function */ data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC); - if (data->wndproc == DefWindowProc) { + if (data->wndproc == WIN_WindowProc) { data->wndproc = NULL; } SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc); From 64169f768287087eb299a2a3e67f705074f99516 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Wed, 9 Jun 2010 00:03:54 -0400 Subject: [PATCH 05/24] Added On_Char method to Window_Listener for WM_CHAR messages. Removed a lot of TSF code because part of it was wrong and part was too complicated. Added Clear method to clear the window. IME input should work in both windowed mode and fullscreen mode with these changes. I have tested on Windows XP SP3 and Windows 7 Ultimate in VirtualBox. When you type a character (with an IME or not), the console will show the code point as U+XXXX. You use Left Alt+Shift (or whatever you have it set to) to switch input languages as usual. Hit ESC to exit (or close the window in windowed mode). The program will pause before exiting so you can review the console output (press a key to exit). --- EXCLUDE/GLTSF/include/App.hpp | 6 + EXCLUDE/GLTSF/include/TSF.hpp | 46 +------ EXCLUDE/GLTSF/include/Window.hpp | 3 + EXCLUDE/GLTSF/include/Window_Listener.hpp | 1 + EXCLUDE/GLTSF/src/App.cpp | 12 +- EXCLUDE/GLTSF/src/Main.cpp | 11 +- EXCLUDE/GLTSF/src/TSF.cpp | 144 ++++------------------ EXCLUDE/GLTSF/src/Window.cpp | 11 +- 8 files changed, 66 insertions(+), 168 deletions(-) diff --git a/EXCLUDE/GLTSF/include/App.hpp b/EXCLUDE/GLTSF/include/App.hpp index 658f73b81..afa9783e1 100644 --- a/EXCLUDE/GLTSF/include/App.hpp +++ b/EXCLUDE/GLTSF/include/App.hpp @@ -17,8 +17,14 @@ class App : public Window_Listener virtual void On_Close(); virtual void On_Key_Down(int Key); virtual void On_Key_Up(int Key); + virtual void On_Char(unsigned int Char); private: + static const int Width = 800; + static const int Height = 600; + static const int Bits_Per_Pixel = 32; + static const bool Fullscreen = false; + Window my_Window; bool my_Done; }; diff --git a/EXCLUDE/GLTSF/include/TSF.hpp b/EXCLUDE/GLTSF/include/TSF.hpp index c37f4a4be..9e58b1e4e 100644 --- a/EXCLUDE/GLTSF/include/TSF.hpp +++ b/EXCLUDE/GLTSF/include/TSF.hpp @@ -7,51 +7,15 @@ class TSF { public: - -protected: - class UI_Sink : public ITfUIElementSink, public ITfInputProcessorProfileActivationSink - { - public: - UI_Sink(); - ~UI_Sink(); - - // IUnknown - STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj); - STDMETHODIMP_(ULONG) AddRef(void); - STDMETHODIMP_(ULONG) Release(void); - - // ITfUIElementSink - STDMETHODIMP BeginUIElement(DWORD dwUIElementId, BOOL *pbShow); - STDMETHODIMP UpdateUIElement(DWORD dwUIElementId); - STDMETHODIMP EndUIElement(DWORD dwUIElementId); - - // ITfInputProcessorProfileActivationSink - STDMETHODIMP OnActivated(DWORD dwProfileType, LANGID langid, - REFCLSID clsid, REFGUID catid, - REFGUID guidProfile, HKL hkl, - DWORD dwFlags); - - // ITfCompartmentEventSink - STDMETHODIMP OnChange(REFGUID rguid); - - private: - LONG my_Reference_Count; - }; - - TSF(); - ~TSF(); - - void Initialize(); - void Finalize(); + static void Initialize(); + static void Finalize(); private: - bool my_COM_Initialized; + TSF(); - CComPtr my_Thread_Manager; - UI_Sink *my_UI_Sink; + static bool COM_Initialized; - DWORD my_UI_Element_Sink_Cookie; - DWORD my_IPPA_Sink_Cookie; + static CComPtr Thread_Manager; }; #endif diff --git a/EXCLUDE/GLTSF/include/Window.hpp b/EXCLUDE/GLTSF/include/Window.hpp index f07fd477a..eda00a5a3 100644 --- a/EXCLUDE/GLTSF/include/Window.hpp +++ b/EXCLUDE/GLTSF/include/Window.hpp @@ -8,6 +8,7 @@ #include "Video_Mode.hpp" #include "Window_Listener.hpp" +#include "TSF.hpp" class Window { @@ -26,6 +27,8 @@ class Window void Update(); void Display(); + void Clear(); + private: static const wchar_t *Window_Class_Name; diff --git a/EXCLUDE/GLTSF/include/Window_Listener.hpp b/EXCLUDE/GLTSF/include/Window_Listener.hpp index 52396f7e8..c99c2418a 100644 --- a/EXCLUDE/GLTSF/include/Window_Listener.hpp +++ b/EXCLUDE/GLTSF/include/Window_Listener.hpp @@ -8,6 +8,7 @@ class Window_Listener virtual void On_Key_Down(int Key){} virtual void On_Key_Up(int Key){} + virtual void On_Char(unsigned int Char){} }; #endif diff --git a/EXCLUDE/GLTSF/src/App.cpp b/EXCLUDE/GLTSF/src/App.cpp index ae8ca73a5..6ce3b5627 100644 --- a/EXCLUDE/GLTSF/src/App.cpp +++ b/EXCLUDE/GLTSF/src/App.cpp @@ -1,20 +1,22 @@ #include "App.hpp" +#include "TSF.hpp" App::App() : my_Done(false) { - + TSF::Initialize(); } App::~App() { Finalize(); + TSF::Finalize(); } void App::Initialize() { Finalize(); - my_Window.Initialize(L"GLTSF", Video_Mode(800, 600, 32), false); + my_Window.Initialize(L"GLTSF", Video_Mode(Width, Height, Bits_Per_Pixel), Fullscreen); my_Window.Set_Listener(this); my_Window.Show(); } @@ -30,6 +32,7 @@ void App::Run() while (!my_Done) { my_Window.Update(); + my_Window.Clear(); my_Window.Display(); } } @@ -54,3 +57,8 @@ void App::On_Key_Up(int Key) { } + +void App::On_Char(unsigned int Char) +{ + printf("Char: U+%04X\n", Char); +} diff --git a/EXCLUDE/GLTSF/src/Main.cpp b/EXCLUDE/GLTSF/src/Main.cpp index 31febadbf..26c975da4 100644 --- a/EXCLUDE/GLTSF/src/Main.cpp +++ b/EXCLUDE/GLTSF/src/Main.cpp @@ -3,6 +3,7 @@ int main(int argc, char *argv[]) { + int Result = EXIT_SUCCESS; try { App theApp; @@ -11,7 +12,13 @@ int main(int argc, char *argv[]) catch (const std::exception& e) { printf("Error: %s\n", e.what()); - return 1; + Result = EXIT_FAILURE; } - return 0; + catch (...) + { + printf("Unhandled exception\n"); + Result = EXIT_FAILURE; + } + system("PAUSE"); + return Result; } diff --git a/EXCLUDE/GLTSF/src/TSF.cpp b/EXCLUDE/GLTSF/src/TSF.cpp index 2f2df17c5..f447e6c5b 100644 --- a/EXCLUDE/GLTSF/src/TSF.cpp +++ b/EXCLUDE/GLTSF/src/TSF.cpp @@ -1,140 +1,40 @@ #include "TSF.hpp" #include -TSF::TSF() : my_COM_Initialized(false), - my_UI_Sink(0), - my_UI_Element_Sink_Cookie(TF_INVALID_COOKIE), - my_IPPA_Sink_Cookie(TF_INVALID_COOKIE) -{ - -} - -TSF::~TSF() -{ - Finalize(); -} +bool TSF::COM_Initialized = false; +CComPtr TSF::Thread_Manager; void TSF::Initialize() { - Finalize(); - - if (S_OK != CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)) - throw std::runtime_error("Failed to initialize COM"); - - my_COM_Initialized = true; - if (S_OK != CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, __uuidof(ITfThreadMgrEx), (void **)&my_Thread_Manager)) - throw std::runtime_error("Failed to create ITfThreadMgrEx instance"); - - TfClientId Client_Id = 0; - if (FAILED(my_Thread_Manager->ActivateEx(&Client_Id, TF_TMAE_UIELEMENTENABLEDONLY))) - throw std::runtime_error("ITfThreadMgrEx::ActivateEx failed"); - - my_UI_Sink = new UI_Sink(); - ITfSource *Source = NULL; - if (FAILED(my_Thread_Manager->QueryInterface(__uuidof(ITfSource), (void **)&Source))) - throw std::runtime_error("QueryInterface failed"); + if (!COM_Initialized) + { + HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (S_OK != hr && S_FALSE != hr) + throw std::runtime_error("Failed to initialize COM"); - if (FAILED(Source->AdviseSink(__uuidof(ITfUIElementSink), (ITfUIElementSink *)my_UI_Sink, &my_UI_Element_Sink_Cookie))) - throw std::runtime_error("AdviseSink failed"); + COM_Initialized = true; + } + if (!Thread_Manager) + { + if (FAILED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfThreadMgr, reinterpret_cast(&Thread_Manager)))) + throw std::runtime_error("Failed to create ITfThreadMgr instance"); - if (FAILED(Source->AdviseSink(__uuidof(ITfInputProcessorProfileActivationSink), (ITfInputProcessorProfileActivationSink *)my_UI_Sink, &my_IPPA_Sink_Cookie))) - throw std::runtime_error("AdviseSink failed"); + TfClientId ClientId; + if (FAILED(Thread_Manager->Activate(&ClientId))) + throw std::runtime_error("ITfThreadMgr::Activate failed"); + } } void TSF::Finalize() { - if (my_UI_Sink) + if (Thread_Manager) { - ITfSource *Source = NULL; - if (SUCCEEDED(my_Thread_Manager->QueryInterface(__uuidof(ITfSource), (void **)&Source))) - { - Source->UnadviseSink(my_IPPA_Sink_Cookie); - Source->UnadviseSink(my_UI_Element_Sink_Cookie); - Source->Release(); - } - if (my_Thread_Manager) - my_Thread_Manager->Deactivate(); - - my_UI_Sink->Release(); - delete my_UI_Sink; - my_UI_Sink = NULL; + Thread_Manager->Deactivate(); + Thread_Manager = NULL; } - my_Thread_Manager = NULL; - if (my_COM_Initialized) + if (COM_Initialized) { CoUninitialize(); - my_COM_Initialized = false; + COM_Initialized = false; } } - -TSF::UI_Sink::UI_Sink() -{ - my_Reference_Count = 1; -} - -TSF::UI_Sink::~UI_Sink() -{ - -} - -STDMETHODIMP TSF::UI_Sink::QueryInterface(REFIID riid, void **ppvObj) -{ - if (NULL == ppvObj) - return E_INVALIDARG; - - *ppvObj = NULL; - if (IsEqualIID(riid, IID_IUnknown)) - *ppvObj = reinterpret_cast(this); - else if (IsEqualIID(riid, __uuidof(ITfUIElementSink))) - *ppvObj = reinterpret_cast(this); - else if (IsEqualIID(riid, __uuidof(ITfInputProcessorProfileActivationSink))) - *ppvObj = reinterpret_cast(this); - else if (IsEqualIID(riid, __uuidof(ITfCompartmentEventSink))) - *ppvObj = reinterpret_cast(this); - - if (*ppvObj) - { - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -ULONG TSF::UI_Sink::AddRef(void) -{ - return ++my_Reference_Count; -} - -ULONG TSF::UI_Sink::Release(void) -{ - LONG Count = --my_Reference_Count; - if (0 == Count) - delete this; - - return Count; -} - -STDMETHODIMP TSF::UI_Sink::BeginUIElement(DWORD dwUIElementId, BOOL *pbShow) -{ - return S_OK; -} - -STDMETHODIMP TSF::UI_Sink::UpdateUIElement(DWORD dwUIElementId) -{ - return S_OK; -} - -STDMETHODIMP TSF::UI_Sink::EndUIElement(DWORD dwUIElementId) -{ - return S_OK; -} - -STDMETHODIMP TSF::UI_Sink::OnActivated(DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags) -{ - return S_OK; -} - -STDMETHODIMP TSF::UI_Sink::OnChange(REFGUID rguid) -{ - return S_OK; -} diff --git a/EXCLUDE/GLTSF/src/Window.cpp b/EXCLUDE/GLTSF/src/Window.cpp index 955693c05..bbb08654a 100644 --- a/EXCLUDE/GLTSF/src/Window.cpp +++ b/EXCLUDE/GLTSF/src/Window.cpp @@ -1,4 +1,5 @@ #include "Window.hpp" +#include #pragma comment(lib, "opengl32.lib") @@ -83,7 +84,7 @@ void Window::Create_Window(const std::wstring &Title, const Video_Mode &Mode, bo int Height = my_Video_Mode.Height; ReleaseDC(NULL, Screen_DC); - DWORD Style = WS_OVERLAPPEDWINDOW; + DWORD Style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; if (!my_Fullscreen) { RECT Rect = {0, 0, Width, Height}; @@ -227,6 +228,9 @@ LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM case WM_KEYUP: Call_Listener(On_Key_Up(wParam)); break; + case WM_CHAR: + Call_Listener(On_Char(wParam)); + break; default: return DefWindowProcW(Handle, Message, wParam, lParam); break; @@ -261,3 +265,8 @@ void Window::Display() if (my_Device_Context && my_GL_Context) SwapBuffers(my_Device_Context); } + +void Window::Clear() +{ + glClear(GL_COLOR_BUFFER_BIT); +} From 1c0f4e9edb45e6978c6c578120feb5bf8ffadaa2 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Wed, 9 Jun 2010 21:36:32 -0400 Subject: [PATCH 06/24] Added else to make things clear. --- src/video/win32/SDL_win32window.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index d69ba6a63..2b8c75fe8 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -115,7 +115,9 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created) if (data->wndproc == WIN_WindowProc) { data->wndproc = NULL; } - SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc); + else { + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc); + } /* Fill in the SDL window with the window data */ { From b5e4ed364796762edc9216981d375f5d2a41fffa Mon Sep 17 00:00:00 2001 From: dewyatt Date: Fri, 11 Jun 2010 18:32:18 -0400 Subject: [PATCH 07/24] Added vs2008 project files for GLTSF (2008 is much faster on my old computer) --- EXCLUDE/GLTSF/GLTSF.vcproj | 231 +++++++++++++++++++++++++++++++++ EXCLUDE/GLTSF/GLTSF_vs2008.sln | 20 +++ 2 files changed, 251 insertions(+) create mode 100644 EXCLUDE/GLTSF/GLTSF.vcproj create mode 100644 EXCLUDE/GLTSF/GLTSF_vs2008.sln diff --git a/EXCLUDE/GLTSF/GLTSF.vcproj b/EXCLUDE/GLTSF/GLTSF.vcproj new file mode 100644 index 000000000..25c8a75bd --- /dev/null +++ b/EXCLUDE/GLTSF/GLTSF.vcproj @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EXCLUDE/GLTSF/GLTSF_vs2008.sln b/EXCLUDE/GLTSF/GLTSF_vs2008.sln new file mode 100644 index 000000000..319a4c0db --- /dev/null +++ b/EXCLUDE/GLTSF/GLTSF_vs2008.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GLTSF", "GLTSF.vcproj", "{FC8A9A48-6667-4BDE-8E9B-5859408AEE83}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FC8A9A48-6667-4BDE-8E9B-5859408AEE83}.Debug|Win32.ActiveCfg = Debug|Win32 + {FC8A9A48-6667-4BDE-8E9B-5859408AEE83}.Debug|Win32.Build.0 = Debug|Win32 + {FC8A9A48-6667-4BDE-8E9B-5859408AEE83}.Release|Win32.ActiveCfg = Release|Win32 + {FC8A9A48-6667-4BDE-8E9B-5859408AEE83}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal From 381873fa15875d4c0168264296da2cf026391a2f Mon Sep 17 00:00:00 2001 From: dewyatt Date: Sat, 12 Jun 2010 03:19:43 -0400 Subject: [PATCH 08/24] Renamed Window::Update to Window::Handle_Events. Removed Window::Clear. Added Window::Show_Cursor/Hide_Cursor. Added On_Resized event. --- EXCLUDE/GLTSF/include/Window.hpp | 5 +++-- EXCLUDE/GLTSF/include/Window_Listener.hpp | 2 +- EXCLUDE/GLTSF/src/Window.cpp | 15 ++++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/EXCLUDE/GLTSF/include/Window.hpp b/EXCLUDE/GLTSF/include/Window.hpp index eda00a5a3..f019cd268 100644 --- a/EXCLUDE/GLTSF/include/Window.hpp +++ b/EXCLUDE/GLTSF/include/Window.hpp @@ -24,10 +24,11 @@ class Window void Show(); void Hide(); - void Update(); + void Handle_Events(); void Display(); - void Clear(); + void Show_Cursor(); + void Hide_Cursor(); private: static const wchar_t *Window_Class_Name; diff --git a/EXCLUDE/GLTSF/include/Window_Listener.hpp b/EXCLUDE/GLTSF/include/Window_Listener.hpp index c99c2418a..a5a96e731 100644 --- a/EXCLUDE/GLTSF/include/Window_Listener.hpp +++ b/EXCLUDE/GLTSF/include/Window_Listener.hpp @@ -5,10 +5,10 @@ class Window_Listener { public: virtual void On_Close(){} - virtual void On_Key_Down(int Key){} virtual void On_Key_Up(int Key){} virtual void On_Char(unsigned int Char){} + virtual void On_Resized(unsigned int Width, unsigned int Height){} }; #endif diff --git a/EXCLUDE/GLTSF/src/Window.cpp b/EXCLUDE/GLTSF/src/Window.cpp index bbb08654a..0160d65ec 100644 --- a/EXCLUDE/GLTSF/src/Window.cpp +++ b/EXCLUDE/GLTSF/src/Window.cpp @@ -17,6 +17,7 @@ Window::Window() : my_Handle(0), Window::~Window() { Finalize(); + Show_Cursor(); } void Window::Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen) @@ -219,6 +220,9 @@ LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM { switch (Message) { + case WM_SIZE: + Call_Listener(On_Resized(LOWORD(lParam), HIWORD(lParam))); + break; case WM_CLOSE: Call_Listener(On_Close()); break; @@ -250,7 +254,7 @@ void Window::Hide() ShowWindow(my_Handle, SW_HIDE); } -void Window::Update() +void Window::Handle_Events() { MSG Message = {0}; while (PeekMessageW(&Message, NULL, 0, 0, PM_REMOVE)) @@ -266,7 +270,12 @@ void Window::Display() SwapBuffers(my_Device_Context); } -void Window::Clear() +void Window::Show_Cursor() +{ + ShowCursor(TRUE); +} + +void Window::Hide_Cursor() { - glClear(GL_COLOR_BUFFER_BIT); + ShowCursor(FALSE); } From 2140ff6c5302f750cc6cfdf52c28f94bab08522e Mon Sep 17 00:00:00 2001 From: dewyatt Date: Sat, 12 Jun 2010 03:21:54 -0400 Subject: [PATCH 09/24] Added support for On_Resized event to App. Added OpenGL code to draw a rotating triangle. Rearranged main loop code. --- EXCLUDE/GLTSF/include/App.hpp | 6 ++++- EXCLUDE/GLTSF/src/App.cpp | 45 +++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/EXCLUDE/GLTSF/include/App.hpp b/EXCLUDE/GLTSF/include/App.hpp index afa9783e1..88cdf41da 100644 --- a/EXCLUDE/GLTSF/include/App.hpp +++ b/EXCLUDE/GLTSF/include/App.hpp @@ -18,12 +18,16 @@ class App : public Window_Listener virtual void On_Key_Down(int Key); virtual void On_Key_Up(int Key); virtual void On_Char(unsigned int Char); + virtual void On_Resized(unsigned int Width, unsigned int Height); private: + void Update(); + void Draw(); + static const int Width = 800; static const int Height = 600; static const int Bits_Per_Pixel = 32; - static const bool Fullscreen = false; + static const bool Fullscreen = true; Window my_Window; bool my_Done; diff --git a/EXCLUDE/GLTSF/src/App.cpp b/EXCLUDE/GLTSF/src/App.cpp index 6ce3b5627..feb8be51c 100644 --- a/EXCLUDE/GLTSF/src/App.cpp +++ b/EXCLUDE/GLTSF/src/App.cpp @@ -1,5 +1,11 @@ #include "App.hpp" #include "TSF.hpp" +#include +#include + +#pragma comment(lib, "glu32.lib") + +GLfloat Rotation = 0.0f; App::App() : my_Done(false) { @@ -19,6 +25,7 @@ void App::Initialize() my_Window.Initialize(L"GLTSF", Video_Mode(Width, Height, Bits_Per_Pixel), Fullscreen); my_Window.Set_Listener(this); my_Window.Show(); + my_Window.Hide_Cursor(); } void App::Finalize() @@ -31,8 +38,10 @@ void App::Run() Initialize(); while (!my_Done) { - my_Window.Update(); - my_Window.Clear(); + my_Window.Handle_Events(); + + Update(); + Draw(); my_Window.Display(); } } @@ -62,3 +71,35 @@ void App::On_Char(unsigned int Char) { printf("Char: U+%04X\n", Char); } + +void App::On_Resized(unsigned int Width, unsigned int Height) +{ + glViewport(0, 0, Width, Height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +void App::Update() +{ + Rotation += 0.2f; +} + +void App::Draw() +{ + glClear(GL_COLOR_BUFFER_BIT); + + glLoadIdentity(); + glRotatef(Rotation, 0.0f, 0.0f, -1.0f); + + glBegin(GL_TRIANGLES); + glColor3f(0.7f, 0.0f, 0.0f); + glVertex3f(0.0f, 0.5f, 0.0f); + glColor3f(0.0f, 0.7f, 0.0f); + glVertex3f(-0.5f, -0.5f, 0.0f); + glColor3f(0.0f, 0.0f, 0.7f); + glVertex3f(0.5f, -0.5f, 0.0f); + glEnd(); +} From 12c7bfb4f1cf758aa4233da5276aa229c4e5da1d Mon Sep 17 00:00:00 2001 From: dewyatt Date: Mon, 21 Jun 2010 17:16:37 -0400 Subject: [PATCH 10/24] Starting to implement ITextStoreACP. It's very incomplete and will probably change quite a bit but it's a start. ITextStoreACP is the minimum interface to be considered TSF-aware. --- EXCLUDE/GLTSF/include/TSF.hpp | 62 +++++++ EXCLUDE/GLTSF/src/TSF.cpp | 309 +++++++++++++++++++++++++++++++++- 2 files changed, 369 insertions(+), 2 deletions(-) diff --git a/EXCLUDE/GLTSF/include/TSF.hpp b/EXCLUDE/GLTSF/include/TSF.hpp index 9e58b1e4e..f6f3fbea8 100644 --- a/EXCLUDE/GLTSF/include/TSF.hpp +++ b/EXCLUDE/GLTSF/include/TSF.hpp @@ -11,11 +11,73 @@ class TSF static void Finalize(); private: + class TSF_Text_Store : public ITextStoreACP, public ITfContextOwnerCompositionSink + { + public: + //IUnknown + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + //ITextStoreACP + STDMETHODIMP AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask); + STDMETHODIMP UnadviseSink(IUnknown *punk); + STDMETHODIMP RequestLock(DWORD dwLockFlags, HRESULT *phrSession); + STDMETHODIMP GetStatus(TS_STATUS *pdcs); + STDMETHODIMP QueryInsert(LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, LONG *pacpResultEnd); + STDMETHODIMP GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched); + STDMETHODIMP SetSelection(ULONG ulCount, const TS_SELECTION_ACP *pSelection); + STDMETHODIMP GetText(LONG acpStart, LONG acpEnd, WCHAR *pchPlain, ULONG cchPlainReq, ULONG *pcchPlainRet, TS_RUNINFO *prgRunInfo, ULONG cRunInfoReq, ULONG *pcRunInfoRet, LONG *pacpNext); + STDMETHODIMP SetText(DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, ULONG cch, TS_TEXTCHANGE *pChange); + STDMETHODIMP GetFormattedText(LONG acpStart, LONG acpEnd, IDataObject **ppDataObject); + STDMETHODIMP GetEmbedded(LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk); + STDMETHODIMP QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable); + STDMETHODIMP InsertEmbedded(DWORD dwFlags, LONG acpStart, LONG acpEnd, IDataObject *pDataObject, TS_TEXTCHANGE *pChange); + STDMETHODIMP InsertTextAtSelection(DWORD dwFlags, const WCHAR *pchText, ULONG cch, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange); + STDMETHODIMP InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange); + STDMETHODIMP RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs); + STDMETHODIMP RequestAttrsAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags); + STDMETHODIMP RequestAttrsTransitioningAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags); + STDMETHODIMP FindNextAttrTransition(LONG acpStart, LONG acpHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset); + STDMETHODIMP RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched); + STDMETHODIMP GetEndACP(LONG *pacp); + STDMETHODIMP GetActiveView(TsViewCookie *pvcView); + STDMETHODIMP GetACPFromPoint(TsViewCookie vcView, const POINT *ptScreen, DWORD dwFlags, LONG *pacp); + STDMETHODIMP GetTextExt(TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, BOOL *pfClipped); + STDMETHODIMP GetScreenExt(TsViewCookie vcView, RECT *prc); + STDMETHODIMP GetWnd(TsViewCookie vcView, HWND *phwnd); + + //ITfOwnerCompositionSink + STDMETHODIMP OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk); + STDMETHODIMP OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew); + STDMETHODIMP OnEndComposition(ITfCompositionView *pComposition); + + void Initialize(); + void Finalize(); + + TSF_Text_Store(); + ~TSF_Text_Store(); + + private: + ULONG my_Reference_Count; + CComPtr my_Document_Manager; + CComPtr my_Context; + DWORD my_Edit_Cookie; + CComPtr my_Sink; + DWORD my_Sink_Mask; + DWORD my_Lock; + DWORD my_Lock_Queued; + CComPtr my_Composition_View; + TS_SELECTION_ACP my_Composition_Selection; + }; + TSF(); static bool COM_Initialized; static CComPtr Thread_Manager; + static TfClientId Client_Id; + static TSF_Text_Store *Text_Store; }; #endif diff --git a/EXCLUDE/GLTSF/src/TSF.cpp b/EXCLUDE/GLTSF/src/TSF.cpp index f447e6c5b..e88d44516 100644 --- a/EXCLUDE/GLTSF/src/TSF.cpp +++ b/EXCLUDE/GLTSF/src/TSF.cpp @@ -3,6 +3,8 @@ bool TSF::COM_Initialized = false; CComPtr TSF::Thread_Manager; +TfClientId TSF::Client_Id; +TSF::TSF_Text_Store *TSF::Text_Store = NULL; void TSF::Initialize() { @@ -19,9 +21,11 @@ void TSF::Initialize() if (FAILED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfThreadMgr, reinterpret_cast(&Thread_Manager)))) throw std::runtime_error("Failed to create ITfThreadMgr instance"); - TfClientId ClientId; - if (FAILED(Thread_Manager->Activate(&ClientId))) + if (FAILED(Thread_Manager->Activate(&Client_Id))) throw std::runtime_error("ITfThreadMgr::Activate failed"); + + Text_Store = new TSF_Text_Store; + Text_Store->Initialize(); } } @@ -38,3 +42,304 @@ void TSF::Finalize() COM_Initialized = false; } } + +STDMETHODIMP TSF::TSF_Text_Store::QueryInterface(REFIID riid, void **ppvObject) +{ + *ppvObject = NULL; + if (IID_IUnknown == riid || IID_ITextStoreACP == riid) + *ppvObject = static_cast(this); + else if (IID_ITfContextOwnerCompositionSink == riid) + *ppvObject = static_cast(this); + + if (*ppvObject) + { + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) TSF::TSF_Text_Store::AddRef() +{ + return ++my_Reference_Count; +} + +STDMETHODIMP_(ULONG) TSF::TSF_Text_Store::Release() +{ + --my_Reference_Count; + if (0 != my_Reference_Count) + return my_Reference_Count; + + delete this; + return 0; +} + +STDMETHODIMP TSF::TSF_Text_Store::AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask) +{ + if (!punk || IID_ITextStoreACPSink != riid) + return E_INVALIDARG; + + if (!my_Sink) + { + punk->QueryInterface(&my_Sink); + if (!my_Sink) + return E_UNEXPECTED; + } + else + { + CComPtr Unknown_1, Unknown_2; + punk->QueryInterface(&Unknown_1); + my_Sink->QueryInterface(&Unknown_2); + if (Unknown_1 != Unknown_2) + return CONNECT_E_ADVISELIMIT; + } + my_Sink_Mask = dwMask; + return S_OK; +} + +STDMETHODIMP TSF::TSF_Text_Store::UnadviseSink(IUnknown *punk) +{ + if (!punk) + return E_INVALIDARG; + + if (!my_Sink) + return CONNECT_E_NOCONNECTION; + + CComPtr Unknown_1, Unknown_2; + punk->QueryInterface(&Unknown_1); + my_Sink->QueryInterface(&Unknown_2); + + if (Unknown_1 != Unknown_2) + return CONNECT_E_NOCONNECTION; + + my_Sink = NULL; + my_Sink_Mask = 0; + return S_OK; +} + +STDMETHODIMP TSF::TSF_Text_Store::RequestLock(DWORD dwLockFlags, HRESULT *phrSession) +{ + if (!my_Sink) + return E_FAIL; + + if (!phrSession) + return E_INVALIDARG; + + if (my_Lock) + { + if (TS_LF_READ == (my_Lock & TS_LF_READWRITE) + && TS_LF_READWRITE == (dwLockFlags & TS_LF_READWRITE) + && !(dwLockFlags & TS_LF_SYNC)) + { + *phrSession = TS_S_ASYNC; + my_Lock_Queued = dwLockFlags & (~TS_LF_SYNC); + } + else + { + *phrSession = TS_E_SYNCHRONOUS; + return E_FAIL; + } + } + else + { + my_Lock = dwLockFlags & (~TS_LF_SYNC); + *phrSession = my_Sink->OnLockGranted(my_Lock); + while (my_Lock_Queued) + { + my_Lock = my_Lock_Queued; + my_Lock_Queued = 0; + my_Sink->OnLockGranted(my_Lock); + } + my_Lock = 0; + } + return S_OK; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetStatus(TS_STATUS *pdcs) +{ + if (!pdcs) + return E_INVALIDARG; + + pdcs->dwDynamicFlags = 0; + pdcs->dwStaticFlags = TS_SS_NOHIDDENTEXT; + return S_OK; +} + +STDMETHODIMP TSF::TSF_Text_Store::QueryInsert(LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, LONG *pacpResultEnd) +{ + if (acpTestStart < 0 || acpTestStart > acpTestEnd || !pacpResultStart || !pacpResultEnd) + return E_INVALIDARG; + + *pacpResultStart = acpTestStart; + *pacpResultEnd = acpTestStart + cch; + return S_OK; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched) +{ + if (TS_LF_READ != (my_Lock & TS_LF_READ)) + return TS_E_NOLOCK; + + if (!ulCount || !pSelection || !pcFetched) + return E_INVALIDARG; + + *pcFetched = 0; + if (TS_DEFAULT_SELECTION != ulIndex && 0 != ulIndex) + return TS_E_NOSELECTION; + + if (my_Composition_View) + { + *pSelection = my_Composition_Selection; + } + else + { + //TODO + } + return S_OK; +} + +STDMETHODIMP TSF::TSF_Text_Store::SetSelection(ULONG ulCount, const TS_SELECTION_ACP *pSelection) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetText(LONG acpStart, LONG acpEnd, WCHAR *pchPlain, ULONG cchPlainReq, ULONG *pcchPlainRet, TS_RUNINFO *prgRunInfo, ULONG cRunInfoReq, ULONG *pcRunInfoRet, LONG *pacpNext) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::SetText(DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, ULONG cch, TS_TEXTCHANGE *pChange) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetFormattedText(LONG acpStart, LONG acpEnd, IDataObject **ppDataObject) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetEmbedded(LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::InsertEmbedded(DWORD dwFlags, LONG acpStart, LONG acpEnd, IDataObject *pDataObject, TS_TEXTCHANGE *pChange) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::InsertTextAtSelection(DWORD dwFlags, const WCHAR *pchText, ULONG cch, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::RequestAttrsAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::RequestAttrsTransitioningAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::FindNextAttrTransition(LONG acpStart, LONG acpHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetEndACP(LONG *pacp) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetActiveView(TsViewCookie *pvcView) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetACPFromPoint(TsViewCookie vcView, const POINT *ptScreen, DWORD dwFlags, LONG *pacp) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetTextExt(TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, BOOL *pfClipped) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetScreenExt(TsViewCookie vcView, RECT *prc) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::GetWnd(TsViewCookie vcView, HWND *phwnd) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk) +{ + *pfOk = FALSE; + return S_OK; +} + +STDMETHODIMP TSF::TSF_Text_Store::OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew) +{ + return E_NOTIMPL; +} + +STDMETHODIMP TSF::TSF_Text_Store::OnEndComposition(ITfCompositionView *pComposition) +{ + return E_NOTIMPL; +} + +TSF::TSF_Text_Store::TSF_Text_Store() : my_Reference_Count(1), + my_Edit_Cookie(0), + my_Lock(0), + my_Lock_Queued(0) +{ + +} + +TSF::TSF_Text_Store::~TSF_Text_Store() +{ + +} + +void TSF::TSF_Text_Store::Initialize() +{ + if (FAILED(Thread_Manager->CreateDocumentMgr(&my_Document_Manager))) + throw std::runtime_error("Failed to create document manager"); + + if (FAILED(my_Document_Manager->CreateContext(Client_Id, 0, static_cast(this), &my_Context, &my_Edit_Cookie))) + throw std::runtime_error("Failed to create document context"); + + if (FAILED(my_Document_Manager->Push(my_Context))) + throw std::runtime_error("Failed to push context"); +} + +void TSF::TSF_Text_Store::Finalize() +{ + +} From affae433c99512f0fa7fca2bf5ab723e7ffb8cc0 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Sun, 27 Jun 2010 22:03:08 -0400 Subject: [PATCH 11/24] Added condition check macros to make the code clear and easier to debug. Updated code to use macros. --- EXCLUDE/GLTSF/src/TSF.cpp | 79 +++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/EXCLUDE/GLTSF/src/TSF.cpp b/EXCLUDE/GLTSF/src/TSF.cpp index e88d44516..4060397ff 100644 --- a/EXCLUDE/GLTSF/src/TSF.cpp +++ b/EXCLUDE/GLTSF/src/TSF.cpp @@ -74,16 +74,22 @@ STDMETHODIMP_(ULONG) TSF::TSF_Text_Store::Release() return 0; } +#define CHECK_CONDITION(condition, retval, function, line) \ + if (!condition) \ + { \ + printf("%s:%d: Condition failure: %s\n", function, line, #condition); \ + } + +#define ENSURE(condition, retval) CHECK_CONDITION(condition, retval, __FUNCTION__, __LINE__) + STDMETHODIMP TSF::TSF_Text_Store::AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask) { - if (!punk || IID_ITextStoreACPSink != riid) - return E_INVALIDARG; + ENSURE(punk && IID_ITextStoreACP == riid, E_INVALIDARG); if (!my_Sink) { - punk->QueryInterface(&my_Sink); - if (!my_Sink) - return E_UNEXPECTED; + HRESULT hr = punk->QueryInterface(&my_Sink); + ENSURE(SUCCEEDED(hr) && my_Sink, E_UNEXPECTED); } else { @@ -99,11 +105,8 @@ STDMETHODIMP TSF::TSF_Text_Store::AdviseSink(REFIID riid, IUnknown *punk, DWORD STDMETHODIMP TSF::TSF_Text_Store::UnadviseSink(IUnknown *punk) { - if (!punk) - return E_INVALIDARG; - - if (!my_Sink) - return CONNECT_E_NOCONNECTION; + ENSURE(punk, E_INVALIDARG); + ENSURE(my_Sink, CONNECT_E_NOCONNECTION); CComPtr Unknown_1, Unknown_2; punk->QueryInterface(&Unknown_1); @@ -119,12 +122,8 @@ STDMETHODIMP TSF::TSF_Text_Store::UnadviseSink(IUnknown *punk) STDMETHODIMP TSF::TSF_Text_Store::RequestLock(DWORD dwLockFlags, HRESULT *phrSession) { - if (!my_Sink) - return E_FAIL; - - if (!phrSession) - return E_INVALIDARG; - + ENSURE(my_Sink, E_FAIL); + ENSURE(phrSession, E_INVALIDARG); if (my_Lock) { if (TS_LF_READ == (my_Lock & TS_LF_READWRITE) @@ -157,9 +156,7 @@ STDMETHODIMP TSF::TSF_Text_Store::RequestLock(DWORD dwLockFlags, HRESULT *phrSes STDMETHODIMP TSF::TSF_Text_Store::GetStatus(TS_STATUS *pdcs) { - if (!pdcs) - return E_INVALIDARG; - + ENSURE(pdcs, E_INVALIDARG); pdcs->dwDynamicFlags = 0; pdcs->dwStaticFlags = TS_SS_NOHIDDENTEXT; return S_OK; @@ -167,8 +164,7 @@ STDMETHODIMP TSF::TSF_Text_Store::GetStatus(TS_STATUS *pdcs) STDMETHODIMP TSF::TSF_Text_Store::QueryInsert(LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, LONG *pacpResultEnd) { - if (acpTestStart < 0 || acpTestStart > acpTestEnd || !pacpResultStart || !pacpResultEnd) - return E_INVALIDARG; + ENSURE(0 <= acpTestStart && acpTestStart <= acpTestEnd && pacpResultStart && pacpResultEnd, E_INVALIDARG); *pacpResultStart = acpTestStart; *pacpResultEnd = acpTestStart + cch; @@ -177,16 +173,11 @@ STDMETHODIMP TSF::TSF_Text_Store::QueryInsert(LONG acpTestStart, LONG acpTestEnd STDMETHODIMP TSF::TSF_Text_Store::GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched) { - if (TS_LF_READ != (my_Lock & TS_LF_READ)) - return TS_E_NOLOCK; - - if (!ulCount || !pSelection || !pcFetched) - return E_INVALIDARG; + ENSURE(TS_LF_READ == (my_Lock && TS_LF_READ), TS_E_NOLOCK); + ENSURE(ulCount && pSelection && pcFetched, E_INVALIDARG); *pcFetched = 0; - if (TS_DEFAULT_SELECTION != ulIndex && 0 != ulIndex) - return TS_E_NOSELECTION; - + ENSURE(TS_DEFAULT_SELECTION == ulIndex || 0 == ulIndex, TS_E_NOSELECTION); if (my_Composition_View) { *pSelection = my_Composition_Selection; @@ -195,6 +186,7 @@ STDMETHODIMP TSF::TSF_Text_Store::GetSelection(ULONG ulIndex, ULONG ulCount, TS_ { //TODO } + *pcFetched = 1; return S_OK; } @@ -205,7 +197,18 @@ STDMETHODIMP TSF::TSF_Text_Store::SetSelection(ULONG ulCount, const TS_SELECTION STDMETHODIMP TSF::TSF_Text_Store::GetText(LONG acpStart, LONG acpEnd, WCHAR *pchPlain, ULONG cchPlainReq, ULONG *pcchPlainRet, TS_RUNINFO *prgRunInfo, ULONG cRunInfoReq, ULONG *pcRunInfoRet, LONG *pacpNext) { - return E_NOTIMPL; + ENSURE(TS_LF_READ == (my_Lock & TS_LF_READ), TS_E_NOLOCK); + ENSURE(pcchPlainRet && (pchPlain || prgRunInfo) + && (!cchPlainReq == !pchPlain) + && (!cRunInfoReq == !prgRunInfo), E_INVALIDARG); + ENSURE(0 <= acpStart && -1 <= acpEnd + && (-1 == acpEnd || acpStart <= acpEnd), TS_E_INVALIDPOS); + + *pcchPlainRet = 0; + if (pchPlain && cchPlainReq) *pchPlain = 0; + if (pcRunInfoRet) *pcRunInfoRet = 0; + //TODO + return S_OK; } STDMETHODIMP TSF::TSF_Text_Store::SetText(DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, ULONG cch, TS_TEXTCHANGE *pChange) @@ -215,16 +218,23 @@ STDMETHODIMP TSF::TSF_Text_Store::SetText(DWORD dwFlags, LONG acpStart, LONG acp STDMETHODIMP TSF::TSF_Text_Store::GetFormattedText(LONG acpStart, LONG acpEnd, IDataObject **ppDataObject) { + //not needed return E_NOTIMPL; } STDMETHODIMP TSF::TSF_Text_Store::GetEmbedded(LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk) { + //not needed return E_NOTIMPL; } STDMETHODIMP TSF::TSF_Text_Store::QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable) { + if (!pfInsertable) + return E_INVALIDARG; + + //Not supported + *pfInsertable = FALSE; return E_NOTIMPL; } @@ -240,31 +250,37 @@ STDMETHODIMP TSF::TSF_Text_Store::InsertTextAtSelection(DWORD dwFlags, const WCH STDMETHODIMP TSF::TSF_Text_Store::InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange) { + //not needed return E_NOTIMPL; } STDMETHODIMP TSF::TSF_Text_Store::RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs) { + //not needed return E_NOTIMPL; } STDMETHODIMP TSF::TSF_Text_Store::RequestAttrsAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags) { + //not needed return E_NOTIMPL; } STDMETHODIMP TSF::TSF_Text_Store::RequestAttrsTransitioningAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags) { + //not needed return E_NOTIMPL; } STDMETHODIMP TSF::TSF_Text_Store::FindNextAttrTransition(LONG acpStart, LONG acpHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset) { + //not needed return E_NOTIMPL; } STDMETHODIMP TSF::TSF_Text_Store::RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched) { + //not needed return E_NOTIMPL; } @@ -300,8 +316,7 @@ STDMETHODIMP TSF::TSF_Text_Store::GetWnd(TsViewCookie vcView, HWND *phwnd) STDMETHODIMP TSF::TSF_Text_Store::OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk) { - *pfOk = FALSE; - return S_OK; + return E_NOTIMPL; } STDMETHODIMP TSF::TSF_Text_Store::OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew) From 19d9eaa460d9cabb218874b800daf698d7ba7e89 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Wed, 30 Jun 2010 17:29:20 -0400 Subject: [PATCH 12/24] Added GLIMM (using IMM instead of TSF) Uses small bit of TSF to fully disable cicero (TSF for non-TSF enabled apps) --- EXCLUDE/GLIMM/GLIMM.sln | 20 ++ EXCLUDE/GLIMM/GLIMM.vcproj | 233 +++++++++++++++++ EXCLUDE/GLIMM/include/App.hpp | 36 +++ EXCLUDE/GLIMM/include/IMM.hpp | 30 +++ EXCLUDE/GLIMM/include/Video_Mode.hpp | 30 +++ EXCLUDE/GLIMM/include/Window.hpp | 62 +++++ EXCLUDE/GLIMM/include/Window_Listener.hpp | 14 ++ EXCLUDE/GLIMM/src/App.cpp | 103 ++++++++ EXCLUDE/GLIMM/src/IMM.cpp | 165 ++++++++++++ EXCLUDE/GLIMM/src/Main.cpp | 24 ++ EXCLUDE/GLIMM/src/Video_Mode.cpp | 100 ++++++++ EXCLUDE/GLIMM/src/Window.cpp | 293 ++++++++++++++++++++++ 12 files changed, 1110 insertions(+) create mode 100644 EXCLUDE/GLIMM/GLIMM.sln create mode 100644 EXCLUDE/GLIMM/GLIMM.vcproj create mode 100644 EXCLUDE/GLIMM/include/App.hpp create mode 100644 EXCLUDE/GLIMM/include/IMM.hpp create mode 100644 EXCLUDE/GLIMM/include/Video_Mode.hpp create mode 100644 EXCLUDE/GLIMM/include/Window.hpp create mode 100644 EXCLUDE/GLIMM/include/Window_Listener.hpp create mode 100644 EXCLUDE/GLIMM/src/App.cpp create mode 100644 EXCLUDE/GLIMM/src/IMM.cpp create mode 100644 EXCLUDE/GLIMM/src/Main.cpp create mode 100644 EXCLUDE/GLIMM/src/Video_Mode.cpp create mode 100644 EXCLUDE/GLIMM/src/Window.cpp diff --git a/EXCLUDE/GLIMM/GLIMM.sln b/EXCLUDE/GLIMM/GLIMM.sln new file mode 100644 index 000000000..6dd674eef --- /dev/null +++ b/EXCLUDE/GLIMM/GLIMM.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GLIMM", "GLIMM.vcproj", "{F21B830F-20A9-4473-B67A-21D1743C6E19}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F21B830F-20A9-4473-B67A-21D1743C6E19}.Debug|Win32.ActiveCfg = Debug|Win32 + {F21B830F-20A9-4473-B67A-21D1743C6E19}.Debug|Win32.Build.0 = Debug|Win32 + {F21B830F-20A9-4473-B67A-21D1743C6E19}.Release|Win32.ActiveCfg = Release|Win32 + {F21B830F-20A9-4473-B67A-21D1743C6E19}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/EXCLUDE/GLIMM/GLIMM.vcproj b/EXCLUDE/GLIMM/GLIMM.vcproj new file mode 100644 index 000000000..5949e86d4 --- /dev/null +++ b/EXCLUDE/GLIMM/GLIMM.vcproj @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EXCLUDE/GLIMM/include/App.hpp b/EXCLUDE/GLIMM/include/App.hpp new file mode 100644 index 000000000..c7609fc37 --- /dev/null +++ b/EXCLUDE/GLIMM/include/App.hpp @@ -0,0 +1,36 @@ +#ifndef APP_HPP +#define APP_HPP + +#include "Window.hpp" + +class App : public Window_Listener +{ +public: + App(); + virtual ~App(); + + void Initialize(); + void Finalize(); + + void Run(); + + virtual void On_Close(); + virtual void On_Key_Down(int Key); + virtual void On_Key_Up(int Key); + virtual void On_Char(unsigned int Char); + virtual void On_Resized(unsigned int Width, unsigned int Height); + +private: + void Update(); + void Draw(); + + static const int Width = 800; + static const int Height = 600; + static const int Bits_Per_Pixel = 32; + static const bool Fullscreen = false; + + Window my_Window; + bool my_Done; +}; + +#endif diff --git a/EXCLUDE/GLIMM/include/IMM.hpp b/EXCLUDE/GLIMM/include/IMM.hpp new file mode 100644 index 000000000..ae2dfb813 --- /dev/null +++ b/EXCLUDE/GLIMM/include/IMM.hpp @@ -0,0 +1,30 @@ +#ifndef IMM_HPP +#define IMM_HPP + +#define WIN32_LEAN_AND_MEAN +#include +#include + +class IMM +{ +public: + IMM(); + ~IMM(); + + void Initialize(HWND Window); + void Finalize(); + + LRESULT Handle_Message(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam, bool &Ate); + +private: + void Update_Input_Locale(); + + bool my_COM_Initialized; + ITfThreadMgr *my_Thread_Manager; + HWND my_Window; + HIMC my_Context; + HKL my_HKL; + bool my_Vertical_Candidates; +}; + +#endif diff --git a/EXCLUDE/GLIMM/include/Video_Mode.hpp b/EXCLUDE/GLIMM/include/Video_Mode.hpp new file mode 100644 index 000000000..00a801400 --- /dev/null +++ b/EXCLUDE/GLIMM/include/Video_Mode.hpp @@ -0,0 +1,30 @@ +#ifndef VIDEO_MODE_HPP +#define VIDEO_MODE_HPP + +#include + +class Video_Mode +{ +public: + Video_Mode(); + Video_Mode(unsigned int The_Width, unsigned int The_Height, unsigned int The_Bits_Per_Pixel); + + static Video_Mode Get_Desktop_Mode(); + + static std::size_t Get_Mode_Count(); + static Video_Mode Get_Mode(std::size_t Index); + + bool Is_Valid() const; + + bool operator==(const Video_Mode &Mode) const; + bool operator!=(const Video_Mode &Mode) const; + + unsigned int Width; + unsigned int Height; + unsigned int Bits_Per_Pixel; + +private: + static void Initialize_Modes(); +}; + +#endif diff --git a/EXCLUDE/GLIMM/include/Window.hpp b/EXCLUDE/GLIMM/include/Window.hpp new file mode 100644 index 000000000..61e8cf7fe --- /dev/null +++ b/EXCLUDE/GLIMM/include/Window.hpp @@ -0,0 +1,62 @@ +#ifndef WINDOW_HPP +#define WINDOW_HPP + +#include + +#define WIN32_LEAN_AND_MEAN +#include + +#include "Video_Mode.hpp" +#include "Window_Listener.hpp" +#include "IMM.hpp" + +class Window +{ +public: + Window(); + ~Window(); + + void Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen); + void Finalize(); + + void Set_Listener(Window_Listener *Listener); + + void Show(); + void Hide(); + + void Handle_Events(); + void Display(); + + void Show_Cursor(); + void Hide_Cursor(); + + HWND Get_Handle(); + +private: + static const wchar_t *Window_Class_Name; + + void Register_Class(); + void Unregister_Class(); + + void Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen); + void Destroy_Window(); + + void Create_Context(const Video_Mode &Mode); + void Destroy_Context(); + + void Switch_To_Fullscreen(const Video_Mode &Mode); + + LRESULT Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam); + + HWND my_Handle; + Video_Mode my_Video_Mode; + bool my_Fullscreen; + HDC my_Device_Context; + HGLRC my_GL_Context; + bool my_Class_Registered; + Window_Listener *my_Listener; + IMM my_IMM; +}; + +#endif diff --git a/EXCLUDE/GLIMM/include/Window_Listener.hpp b/EXCLUDE/GLIMM/include/Window_Listener.hpp new file mode 100644 index 000000000..a5a96e731 --- /dev/null +++ b/EXCLUDE/GLIMM/include/Window_Listener.hpp @@ -0,0 +1,14 @@ +#ifndef WINDOW_LISTENER_HPP +#define WINDOW_LISTENER_HPP + +class Window_Listener +{ +public: + virtual void On_Close(){} + virtual void On_Key_Down(int Key){} + virtual void On_Key_Up(int Key){} + virtual void On_Char(unsigned int Char){} + virtual void On_Resized(unsigned int Width, unsigned int Height){} +}; + +#endif diff --git a/EXCLUDE/GLIMM/src/App.cpp b/EXCLUDE/GLIMM/src/App.cpp new file mode 100644 index 000000000..b2a527c57 --- /dev/null +++ b/EXCLUDE/GLIMM/src/App.cpp @@ -0,0 +1,103 @@ +#include "App.hpp" +#include +#include + +#pragma comment(lib, "glu32.lib") + +GLfloat Rotation = 0.0f; + +App::App() : my_Done(false) +{ + +} + +App::~App() +{ + Finalize(); +} + +void App::Initialize() +{ + Finalize(); + + my_Window.Initialize(L"GLTSF", Video_Mode(Width, Height, Bits_Per_Pixel), Fullscreen); + my_Window.Set_Listener(this); + my_Window.Show(); + my_Window.Hide_Cursor(); +} + +void App::Finalize() +{ + my_Window.Finalize(); +} + +void App::Run() +{ + Initialize(); + while (!my_Done) + { + my_Window.Handle_Events(); + + Update(); + Draw(); + my_Window.Display(); + } +} + +void App::On_Close() +{ + my_Done = true; + my_Window.Hide(); +} + +void App::On_Key_Down(int Key) +{ + switch (Key) + { + case VK_ESCAPE: + On_Close(); + break; + } +} + +void App::On_Key_Up(int Key) +{ + +} + +void App::On_Char(unsigned int Char) +{ + printf("Char: U+%04X\n", Char); +} + +void App::On_Resized(unsigned int Width, unsigned int Height) +{ + glViewport(0, 0, Width, Height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +void App::Update() +{ + Rotation += 0.2f; +} + +void App::Draw() +{ + glClear(GL_COLOR_BUFFER_BIT); + + glLoadIdentity(); + glRotatef(Rotation, 0.0f, 0.0f, -1.0f); + + glBegin(GL_TRIANGLES); + glColor3f(0.7f, 0.0f, 0.0f); + glVertex3f(0.0f, 0.5f, 0.0f); + glColor3f(0.0f, 0.7f, 0.0f); + glVertex3f(-0.5f, -0.5f, 0.0f); + glColor3f(0.0f, 0.0f, 0.7f); + glVertex3f(0.5f, -0.5f, 0.0f); + glEnd(); +} diff --git a/EXCLUDE/GLIMM/src/IMM.cpp b/EXCLUDE/GLIMM/src/IMM.cpp new file mode 100644 index 000000000..0ef3fdc93 --- /dev/null +++ b/EXCLUDE/GLIMM/src/IMM.cpp @@ -0,0 +1,165 @@ +#include "IMM.hpp" +#include + +IMM::IMM() : my_COM_Initialized(false), + my_Thread_Manager(0), + my_Window(0), + my_Context(0), + my_HKL(0), + my_Vertical_Candidates(false) +{ + +} + +IMM::~IMM() +{ + Finalize(); +} + +void IMM::Initialize(HWND Window) +{ + Finalize(); + + my_Window = Window; + + if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) + { + my_COM_Initialized = true; + if (SUCCEEDED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfThreadMgr, reinterpret_cast(&my_Thread_Manager)))) + { + ITfDocumentMgr *Document_Manager = 0; + if (FAILED(my_Thread_Manager->AssociateFocus(Window, NULL, &Document_Manager))) + printf("Warning: ITfThreadMgr->AssociateFocus failed\n"); + + if (Document_Manager) + Document_Manager->Release(); + } + else + printf("Warning: Failed to create ITfThreadMgr instance\n"); + } + else + printf("Warning: Failed to initialize COM\n"); + + ImmDisableTextFrameService(-1); + + my_Context = ImmGetContext(my_Window); + if (!ImmReleaseContext(my_Window, my_Context)) + throw std::runtime_error("Error releasing context"); + + if (!my_Context) + throw std::runtime_error("No context"); + + Update_Input_Locale(); +} + +void IMM::Finalize() +{ + if (my_Thread_Manager) + { + my_Thread_Manager->Release(); + my_Thread_Manager = 0; + } + if (my_COM_Initialized) + { + CoUninitialize(); + my_COM_Initialized = false; + } +} + +#define GET_LANG(hkl) LOWORD((hkl)) +#define GET_PRIMLANG(hkl) ((WORD)PRIMARYLANGID(GET_LANG((hkl)))) +#define GET_SUBLANG(hkl) SUBLANGID(GET_LANG((hkl))) + +void IMM::Update_Input_Locale() +{ + static HKL Previous_HKL = 0; + my_HKL = GetKeyboardLayout(0); + if (Previous_HKL == my_HKL) + return; + + Previous_HKL = my_HKL; + my_Vertical_Candidates = false; + switch (GET_PRIMLANG(my_HKL)) + { + case LANG_CHINESE: + my_Vertical_Candidates = true; + switch (GET_SUBLANG(my_HKL)) + { + case SUBLANG_CHINESE_SIMPLIFIED: + my_Vertical_Candidates = false; + break; + } + break; + case LANG_JAPANESE: + my_Vertical_Candidates = true; + break; + } +} + +LRESULT IMM::Handle_Message(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam, bool &Ate) +{ + Ate = false; + switch (Message) + { + case WM_INPUTLANGCHANGE: + Update_Input_Locale(); + break; + case WM_IME_SETCONTEXT: + lParam = 0; + return DefWindowProcW(my_Window, Message, wParam, lParam); + break; + case WM_IME_STARTCOMPOSITION: + Ate = true; + break; + case WM_IME_COMPOSITION: + { + Ate = true; + HIMC Context = ImmGetContext(Window); + if (!Context) + break; + + if (lParam & GCS_RESULTSTR) + { + LONG Length = ImmGetCompositionStringW(Context, GCS_RESULTSTR, 0, 0); + std::wstring Composition(Length / sizeof(wchar_t), 0); + Length = ImmGetCompositionStringW(Context, GCS_RESULTSTR, &Composition[0], Composition.size() * sizeof(Composition[0])); + printf("GCS_RESULTSTR: "); + for (LONG i = 0; i < Length / sizeof(wchar_t); ++i) + printf("U+%04X ", Composition[i]); + + printf("\n"); + } + if (lParam & GCS_COMPSTR) + { + LONG Length = ImmGetCompositionStringW(Context, GCS_COMPSTR, 0, 0); + std::wstring Composition(Length / sizeof(wchar_t), 0); + Length = ImmGetCompositionStringW(Context, GCS_COMPSTR, &Composition[0], Composition.size() * sizeof(Composition[0])); + printf("GCS_COMPSTR: "); + for (LONG i = 0; i < Length / sizeof(wchar_t); ++i) + printf("U+%04X ", Composition[i]); + + printf("\n"); + } + ImmReleaseContext(Window, Context); + } + break; + case WM_IME_ENDCOMPOSITION: + break; + case WM_IME_NOTIFY: + switch (wParam) + { + case IMN_SETCONVERSIONMODE: + + break; + case IMN_SETOPENSTATUS: + Update_Input_Locale(); + break; + case IMN_OPENCANDIDATE: + case IMN_CHANGECANDIDATE: + Ate = true; + break; + } + break; + } + return 0; +} diff --git a/EXCLUDE/GLIMM/src/Main.cpp b/EXCLUDE/GLIMM/src/Main.cpp new file mode 100644 index 000000000..26c975da4 --- /dev/null +++ b/EXCLUDE/GLIMM/src/Main.cpp @@ -0,0 +1,24 @@ +#include "App.hpp" +#include + +int main(int argc, char *argv[]) +{ + int Result = EXIT_SUCCESS; + try + { + App theApp; + theApp.Run(); + } + catch (const std::exception& e) + { + printf("Error: %s\n", e.what()); + Result = EXIT_FAILURE; + } + catch (...) + { + printf("Unhandled exception\n"); + Result = EXIT_FAILURE; + } + system("PAUSE"); + return Result; +} diff --git a/EXCLUDE/GLIMM/src/Video_Mode.cpp b/EXCLUDE/GLIMM/src/Video_Mode.cpp new file mode 100644 index 000000000..177e8b956 --- /dev/null +++ b/EXCLUDE/GLIMM/src/Video_Mode.cpp @@ -0,0 +1,100 @@ +#include "Video_Mode.hpp" +#include +#include +#define WIN32_LEAN_AND_MEAN +#include + +namespace +{ + + typedef std::vector Video_Mode_List; + Video_Mode_List Supported_Modes; + + struct Compare_Modes + { + bool operator()(const Video_Mode &Mode_1, const Video_Mode &Mode_2) const + { + if (Mode_1.Bits_Per_Pixel > Mode_2.Bits_Per_Pixel) + return true; + else if (Mode_1.Bits_Per_Pixel < Mode_2.Bits_Per_Pixel) + return false; + else if (Mode_1.Width > Mode_2.Width) + return true; + else if (Mode_1.Width < Mode_2.Width) + return false; + else + return Mode_1.Height > Mode_2.Height; + } + }; + +} + +Video_Mode::Video_Mode() : Width(0), + Height(0), + Bits_Per_Pixel(0) +{ + +} + +Video_Mode::Video_Mode(unsigned int The_Width, unsigned int The_Height, unsigned int The_Bits_Per_Pixel) + : Width(The_Width), + Height(The_Height), + Bits_Per_Pixel(The_Bits_Per_Pixel) +{ + +} + +Video_Mode Video_Mode::Get_Desktop_Mode() +{ + DEVMODE Device_Mode = {0}; + Device_Mode.dmSize = sizeof(Device_Mode); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &Device_Mode); + return Video_Mode(Device_Mode.dmPelsWidth, Device_Mode.dmPelsHeight, Device_Mode.dmBitsPerPel); +} + +std::size_t Video_Mode::Get_Mode_Count() +{ + Initialize_Modes(); + return Supported_Modes.size(); +} + +Video_Mode Video_Mode::Get_Mode(std::size_t Index) +{ + Initialize_Modes(); + return Supported_Modes[Index]; +} + +bool Video_Mode::Is_Valid() const +{ + Initialize_Modes(); + return Supported_Modes.end() != std::find(Supported_Modes.begin(), Supported_Modes.end(), *this); +} + +bool Video_Mode::operator==(const Video_Mode &Mode) const +{ + return (Width == Mode.Width + && Height == Mode.Height + && Bits_Per_Pixel == Mode.Bits_Per_Pixel); +} + +bool Video_Mode::operator!=(const Video_Mode &Mode) const +{ + return !(*this == Mode); +} + +void Video_Mode::Initialize_Modes() +{ + static bool Initialized = false; + if (!Initialized) + { + DEVMODE Device_Mode = {0}; + Device_Mode.dmSize = sizeof(Device_Mode); + for (std::size_t i = 0; 0 != EnumDisplaySettings(NULL, i, &Device_Mode); ++i) + { + Video_Mode Mode(Device_Mode.dmPelsWidth, Device_Mode.dmPelsHeight, Device_Mode.dmBitsPerPel); + if (Supported_Modes.end() == std::find(Supported_Modes.begin(), Supported_Modes.end(), Mode)) + Supported_Modes.push_back(Mode); + } + std::sort(Supported_Modes.begin(), Supported_Modes.end(), Compare_Modes()); + } +} diff --git a/EXCLUDE/GLIMM/src/Window.cpp b/EXCLUDE/GLIMM/src/Window.cpp new file mode 100644 index 000000000..10b985353 --- /dev/null +++ b/EXCLUDE/GLIMM/src/Window.cpp @@ -0,0 +1,293 @@ +#include "Window.hpp" +#include + +#pragma comment(lib, "opengl32.lib") + +const wchar_t *Window::Window_Class_Name = L"GLTSF"; + +Window::Window() : my_Handle(0), + my_Device_Context(0), + my_GL_Context(0), + my_Class_Registered(false), + my_Listener(0) +{ + +} + +Window::~Window() +{ + Finalize(); + Show_Cursor(); +} + +void Window::Initialize(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen) +{ + Finalize(); + + my_Video_Mode = Mode; + if (!my_Video_Mode.Is_Valid()) + throw std::runtime_error("Invalid video mode"); + + my_Fullscreen = Fullscreen; + Register_Class(); + Create_Window(Title, Mode, Fullscreen); + my_IMM.Initialize(my_Handle); +} + +void Window::Finalize() +{ + my_IMM.Finalize(); + Destroy_Window(); + Unregister_Class(); +} + +void Window::Set_Listener(Window_Listener *Listener) +{ + my_Listener = Listener; +} + +void Window::Show() +{ + if (my_Handle) + ShowWindow(my_Handle, SW_SHOW); +} + +void Window::Hide() +{ + if (my_Handle) + ShowWindow(my_Handle, SW_HIDE); +} + +void Window::Handle_Events() +{ + MSG Message = {0}; + while (PeekMessageW(&Message, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&Message); + DispatchMessageW(&Message); + } +} + +void Window::Display() +{ + if (my_Device_Context && my_GL_Context) + SwapBuffers(my_Device_Context); +} + +void Window::Show_Cursor() +{ + ShowCursor(TRUE); +} + +void Window::Hide_Cursor() +{ + ShowCursor(FALSE); +} + +HWND Window::Get_Handle() +{ + return my_Handle; +} + +void Window::Register_Class() +{ + WNDCLASSEXW Window_Class = {0}; + Window_Class.cbSize = sizeof(Window_Class); + Window_Class.style = 0; + Window_Class.lpfnWndProc = &Window::Window_Procedure; + Window_Class.cbClsExtra = 0; + Window_Class.cbWndExtra = 0; + Window_Class.hInstance = GetModuleHandle(NULL); + Window_Class.hIcon = NULL; + Window_Class.hCursor = NULL; + Window_Class.hbrBackground = NULL; + Window_Class.lpszMenuName = NULL; + Window_Class.lpszClassName = Window_Class_Name; + Window_Class.hIconSm = NULL; + if (0 == RegisterClassExW(&Window_Class)) + throw std::runtime_error("Failed to register window class"); + + my_Class_Registered = true; +} + +void Window::Unregister_Class() +{ + if (my_Class_Registered) + { + if (0 == UnregisterClassW(Window_Class_Name, GetModuleHandle(NULL))) + printf("Warning: Failed to unregister window class\n"); + + my_Class_Registered = false; + } +} + +void Window::Create_Window(const std::wstring &Title, const Video_Mode &Mode, bool Fullscreen) +{ + HDC Screen_DC = GetDC(NULL); + int Left = (GetDeviceCaps(Screen_DC, HORZRES) - my_Video_Mode.Width) / 2; + int Top = (GetDeviceCaps(Screen_DC, VERTRES) - my_Video_Mode.Height) / 2; + int Width = my_Video_Mode.Width; + int Height = my_Video_Mode.Height; + ReleaseDC(NULL, Screen_DC); + + DWORD Style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; + if (!my_Fullscreen) + { + RECT Rect = {0, 0, Width, Height}; + AdjustWindowRect(&Rect, Style, false); + Width = Rect.right - Rect.left; + Height = Rect.bottom - Rect.top; + } + my_Handle = CreateWindowW(Window_Class_Name, Title.c_str(), Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this); + if (!my_Handle) + throw std::runtime_error("Failed to create window"); + + if (Fullscreen) + Switch_To_Fullscreen(Mode); + + Create_Context(Mode); + + RECT Rect = {0}; + GetClientRect(my_Handle, &Rect); + //TODO: ... +} + +void Window::Destroy_Window() +{ + Destroy_Context(); + if (my_Handle) + { + DestroyWindow(my_Handle); + my_Handle = 0; + + if (my_Fullscreen) + ChangeDisplaySettings(NULL, 0); + } +} + +void Window::Create_Context(const Video_Mode &Mode) +{ + my_Device_Context = GetDC(my_Handle); + if (!my_Device_Context) + throw std::runtime_error("Failed to get device context"); + + PIXELFORMATDESCRIPTOR Pixel_Descriptor = {0}; + Pixel_Descriptor.nSize = sizeof(Pixel_Descriptor); + Pixel_Descriptor.nVersion = 1; + Pixel_Descriptor.iLayerType = PFD_MAIN_PLANE; + Pixel_Descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + Pixel_Descriptor.iPixelType = PFD_TYPE_RGBA; + Pixel_Descriptor.cColorBits = static_cast(Mode.Bits_Per_Pixel); + Pixel_Descriptor.cDepthBits = 24; + Pixel_Descriptor.cStencilBits = 8; + Pixel_Descriptor.cAlphaBits = Mode.Bits_Per_Pixel == 32 ? 8 : 0; + + int Best_Format = ChoosePixelFormat(my_Device_Context, &Pixel_Descriptor); + if (0 == Best_Format) + throw std::runtime_error("Failed to find suitable pixel format"); + + PIXELFORMATDESCRIPTOR Actual_Format = {0}; + Actual_Format.nSize = sizeof(Actual_Format); + Actual_Format.nVersion = 1; + DescribePixelFormat(my_Device_Context, Best_Format, sizeof(Actual_Format), &Actual_Format); + if (!SetPixelFormat(my_Device_Context, Best_Format, &Actual_Format)) + throw std::runtime_error("Failed to set device pixel format"); + + my_GL_Context = wglCreateContext(my_Device_Context); + if (!my_GL_Context) + throw std::runtime_error("Failed to create OpenGL context"); + + wglMakeCurrent(my_Device_Context, my_GL_Context); +} + +void Window::Destroy_Context() +{ + if (my_GL_Context) + { + wglDeleteContext(my_GL_Context); + my_GL_Context = 0; + } + if (my_Device_Context) + { + ReleaseDC(my_Handle, my_Device_Context); + my_Device_Context = 0; + } +} + +void Window::Switch_To_Fullscreen(const Video_Mode &Mode) +{ + DEVMODE Device_Mode = {0}; + Device_Mode.dmSize = sizeof(Device_Mode); + Device_Mode.dmPelsWidth = Mode.Width; + Device_Mode.dmPelsHeight = Mode.Height; + Device_Mode.dmBitsPerPel = Mode.Bits_Per_Pixel; + Device_Mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + + if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&Device_Mode, CDS_FULLSCREEN)) + throw std::runtime_error("Failed to change to fullscreen mode"); + + SetWindowLong(my_Handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + SetWindowLong(my_Handle, GWL_EXSTYLE, WS_EX_APPWINDOW); + + SetWindowPos(my_Handle, HWND_TOP, 0, 0, Mode.Width, Mode.Height, SWP_FRAMECHANGED); +} + +LRESULT CALLBACK Window::Window_Procedure(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam) +{ + switch (Message) + { + case WM_CREATE: + { + LONG This = reinterpret_cast(reinterpret_cast(lParam)->lpCreateParams); + SetWindowLongPtr(Handle, GWLP_USERDATA, This); + return 0; + } + break; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + break; + default: + { + Window* Win = reinterpret_cast(GetWindowLongPtr(Handle, GWLP_USERDATA)); + if (Win) + return Win->Handle_Message(Handle, Message, wParam, lParam); + } + break; + } + return DefWindowProcW(Handle, Message, wParam, lParam); +} + +#define Call_Listener(x)\ + if (my_Listener) my_Listener->x + +LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam) +{ + bool IMM_Message = false; + LRESULT Result = my_IMM.Handle_Message(Handle, Message, wParam, lParam, IMM_Message); + if (IMM_Message) + return Result; + + switch (Message) + { + case WM_SIZE: + Call_Listener(On_Resized(LOWORD(lParam), HIWORD(lParam))); + break; + case WM_CLOSE: + Call_Listener(On_Close()); + break; + case WM_KEYDOWN: + Call_Listener(On_Key_Down(wParam)); + break; + case WM_KEYUP: + Call_Listener(On_Key_Up(wParam)); + break; + case WM_CHAR: + Call_Listener(On_Char(wParam)); + break; + default: + return DefWindowProcW(Handle, Message, wParam, lParam); + break; + } + return 0; +} From 7cdf7fd299db41946603163d5621b9f16119cfbf Mon Sep 17 00:00:00 2001 From: dewyatt Date: Sun, 4 Jul 2010 06:07:38 -0400 Subject: [PATCH 13/24] Added Get_IMM method to Window. Added focus gain/loss events for IMM. --- EXCLUDE/GLIMM/include/Window.hpp | 1 + EXCLUDE/GLIMM/src/Window.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/EXCLUDE/GLIMM/include/Window.hpp b/EXCLUDE/GLIMM/include/Window.hpp index 61e8cf7fe..dc465d421 100644 --- a/EXCLUDE/GLIMM/include/Window.hpp +++ b/EXCLUDE/GLIMM/include/Window.hpp @@ -31,6 +31,7 @@ class Window void Hide_Cursor(); HWND Get_Handle(); + IMM &Get_IMM(); private: static const wchar_t *Window_Class_Name; diff --git a/EXCLUDE/GLIMM/src/Window.cpp b/EXCLUDE/GLIMM/src/Window.cpp index 10b985353..dc00303e9 100644 --- a/EXCLUDE/GLIMM/src/Window.cpp +++ b/EXCLUDE/GLIMM/src/Window.cpp @@ -89,6 +89,11 @@ HWND Window::Get_Handle() return my_Handle; } +IMM & Window::Get_IMM() +{ + return my_IMM; +} + void Window::Register_Class() { WNDCLASSEXW Window_Class = {0}; @@ -285,6 +290,12 @@ LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM case WM_CHAR: Call_Listener(On_Char(wParam)); break; + case WM_SETFOCUS: + my_IMM.Focus_Gained(); + break; + case WM_KILLFOCUS: + my_IMM.Focus_Lost(); + break; default: return DefWindowProcW(Handle, Message, wParam, lParam); break; From 0c8007354258b248babb7bee4809cf9a516919b5 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Sun, 4 Jul 2010 06:15:42 -0400 Subject: [PATCH 14/24] Fixed window title (from GLTSF to GLIMM). --- EXCLUDE/GLIMM/src/App.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/EXCLUDE/GLIMM/src/App.cpp b/EXCLUDE/GLIMM/src/App.cpp index b2a527c57..e3da11c45 100644 --- a/EXCLUDE/GLIMM/src/App.cpp +++ b/EXCLUDE/GLIMM/src/App.cpp @@ -20,7 +20,7 @@ void App::Initialize() { Finalize(); - my_Window.Initialize(L"GLTSF", Video_Mode(Width, Height, Bits_Per_Pixel), Fullscreen); + my_Window.Initialize(L"GLIMM", Video_Mode(Width, Height, Bits_Per_Pixel), Fullscreen); my_Window.Set_Listener(this); my_Window.Show(); my_Window.Hide_Cursor(); @@ -57,6 +57,9 @@ void App::On_Key_Down(int Key) case VK_ESCAPE: On_Close(); break; + case VK_TAB: + my_Window.Get_IMM().Toggle(); + break; } } From 458b461e1230e386586bf74b40d34e6fc36f91cc Mon Sep 17 00:00:00 2001 From: dewyatt Date: Tue, 6 Jul 2010 02:00:15 -0400 Subject: [PATCH 15/24] Added mouse button click to toggle IMM. --- EXCLUDE/GLIMM/include/App.hpp | 3 ++- EXCLUDE/GLIMM/src/App.cpp | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/EXCLUDE/GLIMM/include/App.hpp b/EXCLUDE/GLIMM/include/App.hpp index c7609fc37..5c9ff3efa 100644 --- a/EXCLUDE/GLIMM/include/App.hpp +++ b/EXCLUDE/GLIMM/include/App.hpp @@ -19,6 +19,7 @@ class App : public Window_Listener virtual void On_Key_Up(int Key); virtual void On_Char(unsigned int Char); virtual void On_Resized(unsigned int Width, unsigned int Height); + virtual void On_Mouse_Button_Down(Mouse_Button Button); private: void Update(); @@ -27,7 +28,7 @@ class App : public Window_Listener static const int Width = 800; static const int Height = 600; static const int Bits_Per_Pixel = 32; - static const bool Fullscreen = false; + static const bool Fullscreen = true; Window my_Window; bool my_Done; diff --git a/EXCLUDE/GLIMM/src/App.cpp b/EXCLUDE/GLIMM/src/App.cpp index e3da11c45..393ac5b88 100644 --- a/EXCLUDE/GLIMM/src/App.cpp +++ b/EXCLUDE/GLIMM/src/App.cpp @@ -57,9 +57,6 @@ void App::On_Key_Down(int Key) case VK_ESCAPE: On_Close(); break; - case VK_TAB: - my_Window.Get_IMM().Toggle(); - break; } } @@ -83,6 +80,16 @@ void App::On_Resized(unsigned int Width, unsigned int Height) glLoadIdentity(); } +void App::On_Mouse_Button_Down(Mouse_Button Button) +{ + switch (Button) + { + case Mouse_Button_Left: + my_Window.Get_IMM().Toggle(); + break; + } +} + void App::Update() { Rotation += 0.2f; From ba3a2361a54d9b176a23b042fb57178a5814bf91 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Tue, 6 Jul 2010 02:06:17 -0400 Subject: [PATCH 16/24] Many changes, preparing to pull/merge main repo to get SDL_GetKeyboardFocus. --- EXCLUDE/GLIMM/include/IMM.hpp | 11 +++ EXCLUDE/GLIMM/include/Window_Listener.hpp | 9 +++ EXCLUDE/GLIMM/src/IMM.cpp | 96 ++++++++++++++++++++--- EXCLUDE/GLIMM/src/Window.cpp | 13 +++ 4 files changed, 117 insertions(+), 12 deletions(-) diff --git a/EXCLUDE/GLIMM/include/IMM.hpp b/EXCLUDE/GLIMM/include/IMM.hpp index ae2dfb813..45be3d61f 100644 --- a/EXCLUDE/GLIMM/include/IMM.hpp +++ b/EXCLUDE/GLIMM/include/IMM.hpp @@ -16,8 +16,18 @@ class IMM LRESULT Handle_Message(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam, bool &Ate); + void Enable(); + void Disable(); + bool Is_Enabled(); + void Toggle(); + + void Focus_Gained(); + void Focus_Lost(); + private: void Update_Input_Locale(); + void Cancel_Composition(); + void Input_Language_Changed(); bool my_COM_Initialized; ITfThreadMgr *my_Thread_Manager; @@ -25,6 +35,7 @@ class IMM HIMC my_Context; HKL my_HKL; bool my_Vertical_Candidates; + bool my_Enabled; }; #endif diff --git a/EXCLUDE/GLIMM/include/Window_Listener.hpp b/EXCLUDE/GLIMM/include/Window_Listener.hpp index a5a96e731..206dd50ba 100644 --- a/EXCLUDE/GLIMM/include/Window_Listener.hpp +++ b/EXCLUDE/GLIMM/include/Window_Listener.hpp @@ -1,6 +1,12 @@ #ifndef WINDOW_LISTENER_HPP #define WINDOW_LISTENER_HPP +enum Mouse_Button +{ + Mouse_Button_Left, + Mouse_Button_Right +}; + class Window_Listener { public: @@ -9,6 +15,9 @@ class Window_Listener virtual void On_Key_Up(int Key){} virtual void On_Char(unsigned int Char){} virtual void On_Resized(unsigned int Width, unsigned int Height){} + virtual void On_Mouse_Button_Down(Mouse_Button Button){} + virtual void On_Mouse_Button_Up(Mouse_Button Button){} + }; #endif diff --git a/EXCLUDE/GLIMM/src/IMM.cpp b/EXCLUDE/GLIMM/src/IMM.cpp index 0ef3fdc93..c949ae4a5 100644 --- a/EXCLUDE/GLIMM/src/IMM.cpp +++ b/EXCLUDE/GLIMM/src/IMM.cpp @@ -6,7 +6,8 @@ IMM::IMM() : my_COM_Initialized(false), my_Window(0), my_Context(0), my_HKL(0), - my_Vertical_Candidates(false) + my_Vertical_Candidates(false), + my_Enabled(false) { } @@ -28,11 +29,13 @@ void IMM::Initialize(HWND Window) if (SUCCEEDED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfThreadMgr, reinterpret_cast(&my_Thread_Manager)))) { ITfDocumentMgr *Document_Manager = 0; - if (FAILED(my_Thread_Manager->AssociateFocus(Window, NULL, &Document_Manager))) + if (SUCCEEDED(my_Thread_Manager->AssociateFocus(Window, NULL, &Document_Manager))) + { + if (Document_Manager) + Document_Manager->Release(); + } + else printf("Warning: ITfThreadMgr->AssociateFocus failed\n"); - - if (Document_Manager) - Document_Manager->Release(); } else printf("Warning: Failed to create ITfThreadMgr instance\n"); @@ -40,16 +43,16 @@ void IMM::Initialize(HWND Window) else printf("Warning: Failed to initialize COM\n"); - ImmDisableTextFrameService(-1); + ImmDisableTextFrameService((DWORD)-1); my_Context = ImmGetContext(my_Window); - if (!ImmReleaseContext(my_Window, my_Context)) - throw std::runtime_error("Error releasing context"); - + ImmReleaseContext(my_Window, my_Context); if (!my_Context) - throw std::runtime_error("No context"); + throw std::runtime_error("No context (No IME installed?)"); Update_Input_Locale(); + Cancel_Composition(); + Disable(); } void IMM::Finalize() @@ -102,11 +105,10 @@ LRESULT IMM::Handle_Message(HWND Window, UINT Message, WPARAM wParam, LPARAM lPa switch (Message) { case WM_INPUTLANGCHANGE: - Update_Input_Locale(); + Input_Language_Changed(); break; case WM_IME_SETCONTEXT: lParam = 0; - return DefWindowProcW(my_Window, Message, wParam, lParam); break; case WM_IME_STARTCOMPOSITION: Ate = true; @@ -158,8 +160,78 @@ LRESULT IMM::Handle_Message(HWND Window, UINT Message, WPARAM wParam, LPARAM lPa case IMN_CHANGECANDIDATE: Ate = true; break; + case IMN_CLOSECANDIDATE: + Ate = true; + break; + default: + Ate = true; + break; } break; } return 0; } + +void IMM::Enable() +{ + ImmAssociateContext(my_Window, my_Context); + Update_Input_Locale(); + my_Enabled = true; + printf("* Enabled\n"); +} + +void IMM::Disable() +{ + ImmAssociateContext(my_Window, 0); + my_Enabled = false; + printf("* Disabled\n"); +} + +bool IMM::Is_Enabled() +{ + return my_Enabled; +} + +void IMM::Toggle() +{ + if (my_Enabled) + Disable(); + else + Enable(); +} + +void IMM::Focus_Gained() +{ + if (my_Enabled) + Enable(); +} + +void IMM::Focus_Lost() +{ + bool Enabled = my_Enabled; + Cancel_Composition(); + Disable(); + my_Enabled = Enabled; +} + +void IMM::Cancel_Composition() +{ + HIMC hIMC = ImmGetContext(my_Window); + if (!hIMC) + return; + + ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0); + ImmNotifyIME(hIMC, NI_CLOSECANDIDATE, 0, 0); + ImmReleaseContext(my_Window, hIMC); +} + +void IMM::Input_Language_Changed() +{ + Update_Input_Locale(); + HWND hwndImeDef = ImmGetDefaultIMEWnd(my_Window); + if (hwndImeDef) + { + SendMessageA(hwndImeDef, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0); + SendMessageA(hwndImeDef, WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0); + } +} diff --git a/EXCLUDE/GLIMM/src/Window.cpp b/EXCLUDE/GLIMM/src/Window.cpp index dc00303e9..eb59121ab 100644 --- a/EXCLUDE/GLIMM/src/Window.cpp +++ b/EXCLUDE/GLIMM/src/Window.cpp @@ -31,6 +31,7 @@ void Window::Initialize(const std::wstring &Title, const Video_Mode &Mode, bool my_Fullscreen = Fullscreen; Register_Class(); Create_Window(Title, Mode, Fullscreen); + Show(); my_IMM.Initialize(my_Handle); } @@ -296,6 +297,18 @@ LRESULT Window::Handle_Message(HWND Handle, UINT Message, WPARAM wParam, LPARAM case WM_KILLFOCUS: my_IMM.Focus_Lost(); break; + case WM_LBUTTONDOWN: + Call_Listener(On_Mouse_Button_Down(Mouse_Button_Left)); + break; + case WM_LBUTTONUP: + Call_Listener(On_Mouse_Button_Up(Mouse_Button_Left)); + break; + case WM_RBUTTONDOWN: + Call_Listener(On_Mouse_Button_Down(Mouse_Button_Right)); + break; + case WM_RBUTTONUP: + Call_Listener(On_Mouse_Button_Up(Mouse_Button_Right)); + break; default: return DefWindowProcW(Handle, Message, wParam, lParam); break; From fb05f1af0a8ac9bb5452d343c2751c21541b6657 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Tue, 6 Jul 2010 02:34:49 -0400 Subject: [PATCH 17/24] Added empty text input functions for win32. --- src/video/win32/SDL_win32keyboard.c | 19 +++++++++++++++++++ src/video/win32/SDL_win32keyboard.h | 4 ++++ src/video/win32/SDL_win32video.c | 3 +++ 3 files changed, 26 insertions(+) diff --git a/src/video/win32/SDL_win32keyboard.c b/src/video/win32/SDL_win32keyboard.c index fb4e0ff41..6f0cc410d 100644 --- a/src/video/win32/SDL_win32keyboard.c +++ b/src/video/win32/SDL_win32keyboard.c @@ -122,4 +122,23 @@ WIN_QuitKeyboard(_THIS) { } +void +WIN_StartTextInput(_THIS) +{ + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + +} + +void +WIN_StopTextInput(_THIS) +{ + +} + +void +WIN_SetTextInputRect(_THIS, SDL_Rect *rect) +{ + +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32keyboard.h b/src/video/win32/SDL_win32keyboard.h index c67410a63..76894931e 100644 --- a/src/video/win32/SDL_win32keyboard.h +++ b/src/video/win32/SDL_win32keyboard.h @@ -31,6 +31,10 @@ extern void WIN_InitKeyboard(_THIS); extern void WIN_UpdateKeymap(void); extern void WIN_QuitKeyboard(_THIS); +extern void WIN_StartTextInput(_THIS); +extern void WIN_StopTextInput(_THIS); +extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect); + #endif /* _SDL_win32keyboard_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32video.c b/src/video/win32/SDL_win32video.c index c93d4f72e..40b5a3b72 100644 --- a/src/video/win32/SDL_win32video.c +++ b/src/video/win32/SDL_win32video.c @@ -162,6 +162,9 @@ WIN_CreateDevice(int devindex) device->GL_SwapWindow = WIN_GL_SwapWindow; device->GL_DeleteContext = WIN_GL_DeleteContext; #endif + device->StartTextInput = WIN_StartTextInput; + device->StopTextInput = WIN_StartTextInput; + device->SetTextInputRect = WIN_SetTextInputRect; device->free = WIN_DeleteDevice; From 63f58db79a8d1a34a220211a0c4af8dea634ae64 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Tue, 6 Jul 2010 03:27:22 -0400 Subject: [PATCH 18/24] Added missing line to make things compile. --- src/video/win32/SDL_win32keyboard.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video/win32/SDL_win32keyboard.c b/src/video/win32/SDL_win32keyboard.c index 6f0cc410d..cbb760d0d 100644 --- a/src/video/win32/SDL_win32keyboard.c +++ b/src/video/win32/SDL_win32keyboard.c @@ -125,7 +125,8 @@ WIN_QuitKeyboard(_THIS) void WIN_StartTextInput(_THIS) { - HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + SDL_Window *window = SDL_GetKeyboardFocus(); + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; } From 91645b5dea6cefb1a85f125c318494fa193a7f95 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 6 Jul 2010 08:22:36 -0700 Subject: [PATCH 19/24] Fixed fullscreen window position Fixed position calculation for centered windows --- src/video/win32/SDL_win32window.c | 33 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index b3e4c3171..79e04d71d 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -186,7 +186,6 @@ WIN_CreateWindow(_THIS, SDL_Window * window) { SDL_VideoDisplay *display = window->display; HWND hwnd; - HWND top; RECT rect; SDL_Rect bounds; DWORD style = (WS_CLIPSIBLINGS | WS_CLIPCHILDREN); @@ -204,11 +203,6 @@ WIN_CreateWindow(_THIS, SDL_Window * window) } /* Figure out what the window area will be */ - if (window->flags & SDL_WINDOW_FULLSCREEN) { - top = HWND_TOPMOST; - } else { - top = HWND_NOTOPMOST; - } rect.left = 0; rect.top = 0; rect.right = window->w; @@ -218,9 +212,17 @@ WIN_CreateWindow(_THIS, SDL_Window * window) h = (rect.bottom - rect.top); WIN_GetDisplayBounds(_this, display, &bounds); + if (window->flags & SDL_WINDOW_FULLSCREEN) { + /* The bounds when this window is visible is the fullscreen mode */ + SDL_DisplayMode fullscreen_mode; + if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) { + bounds.w = fullscreen_mode.w; + bounds.h = fullscreen_mode.h; + } + } if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) { - x = bounds.x + (bounds.w - window->w) / 2; + x = bounds.x + (bounds.w - w) / 2; } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { if (bounds.x == 0) { x = CW_USEDEFAULT; @@ -232,7 +234,7 @@ WIN_CreateWindow(_THIS, SDL_Window * window) } if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) { - y = bounds.y + (bounds.h - window->h) / 2; + y = bounds.y + (bounds.h - h) / 2; } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { if (bounds.x == 0) { y = CW_USEDEFAULT; @@ -389,6 +391,7 @@ WIN_SetWindowPosition(_THIS, SDL_Window * window) HWND top; BOOL menu; int x, y; + int w, h; /* Figure out what the window area will be */ if (window->flags & SDL_WINDOW_FULLSCREEN) { @@ -407,17 +410,27 @@ WIN_SetWindowPosition(_THIS, SDL_Window * window) menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL); #endif AdjustWindowRectEx(&rect, style, menu, 0); + w = (rect.right - rect.left); + h = (rect.bottom - rect.top); WIN_GetDisplayBounds(_this, display, &bounds); + if (window->flags & SDL_WINDOW_FULLSCREEN) { + /* The bounds when this window is visible is the fullscreen mode */ + SDL_DisplayMode fullscreen_mode; + if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) { + bounds.w = fullscreen_mode.w; + bounds.h = fullscreen_mode.h; + } + } if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) { - x = bounds.x + (bounds.w - window->w) / 2; + x = bounds.x + (bounds.w - w) / 2; } else { x = bounds.x + window->x + rect.left; } if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) { - y = bounds.y + (bounds.h - window->h) / 2; + y = bounds.y + (bounds.h - h) / 2; } else { y = bounds.y + window->y + rect.top; } From cbd5b5b32e14bf84ea55f5b47ba60a7045480a44 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Thu, 8 Jul 2010 01:35:47 -0400 Subject: [PATCH 20/24] Changed StartTextInput to take an SDL_Window parameter. --- include/SDL_keyboard.h | 2 +- src/SDL_compat.c | 2 +- src/events/SDL_keyboard.c | 2 +- src/video/SDL_sysvideo.h | 2 +- src/video/SDL_video.c | 4 ++-- src/video/win32/SDL_win32keyboard.c | 3 +-- src/video/win32/SDL_win32keyboard.h | 2 +- src/video/win32/SDL_win32video.c | 2 +- 8 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/SDL_keyboard.h b/include/SDL_keyboard.h index 4482ac028..fca34506f 100644 --- a/include/SDL_keyboard.h +++ b/include/SDL_keyboard.h @@ -140,7 +140,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDLKey key); * \sa SDL_StopTextInput() * \sa SDL_SetTextInputRect() */ -extern DECLSPEC void SDLCALL SDL_StartTextInput(void); +extern DECLSPEC void SDLCALL SDL_StartTextInput(SDL_Window *window); /** * \brief Stop receiving any text input events. diff --git a/src/SDL_compat.c b/src/SDL_compat.c index bb8e46ba8..51b9b5ceb 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -1740,7 +1740,7 @@ SDL_EnableUNICODE(int enable) switch (enable) { case 1: SDL_enabled_UNICODE = 1; - SDL_StartTextInput(); + SDL_StartTextInput(SDL_VideoWindow); break; case 0: SDL_enabled_UNICODE = 0; diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index f25bc6af8..5de1116e3 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -617,7 +617,7 @@ SDL_SetKeyboardFocus(SDL_Window * window) 0, 0); if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) { - SDL_StartTextInput(); + SDL_StartTextInput(window); } } } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 0a82717ec..69ecb440d 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -299,7 +299,7 @@ struct SDL_VideoDevice void (*SuspendScreenSaver) (_THIS); /* Text input */ - void (*StartTextInput) (_THIS); + void (*StartTextInput) (_THIS, SDL_Window *window); void (*StopTextInput) (_THIS); void (*SetTextInputRect) (_THIS, SDL_Rect *rect); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index db8b5d3cb..744defea4 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -3385,10 +3385,10 @@ SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info) } void -SDL_StartTextInput(void) +SDL_StartTextInput(SDL_Window *window) { if (_this && _this->StartTextInput) { - _this->StartTextInput(_this); + _this->StartTextInput(_this, window); } SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE); SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE); diff --git a/src/video/win32/SDL_win32keyboard.c b/src/video/win32/SDL_win32keyboard.c index cbb760d0d..4ee297be7 100644 --- a/src/video/win32/SDL_win32keyboard.c +++ b/src/video/win32/SDL_win32keyboard.c @@ -123,9 +123,8 @@ WIN_QuitKeyboard(_THIS) } void -WIN_StartTextInput(_THIS) +WIN_StartTextInput(_THIS, SDL_Window *window) { - SDL_Window *window = SDL_GetKeyboardFocus(); HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; } diff --git a/src/video/win32/SDL_win32keyboard.h b/src/video/win32/SDL_win32keyboard.h index 76894931e..d9e54b3bd 100644 --- a/src/video/win32/SDL_win32keyboard.h +++ b/src/video/win32/SDL_win32keyboard.h @@ -31,7 +31,7 @@ extern void WIN_InitKeyboard(_THIS); extern void WIN_UpdateKeymap(void); extern void WIN_QuitKeyboard(_THIS); -extern void WIN_StartTextInput(_THIS); +extern void WIN_StartTextInput(_THIS, SDL_Window *window); extern void WIN_StopTextInput(_THIS); extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect); diff --git a/src/video/win32/SDL_win32video.c b/src/video/win32/SDL_win32video.c index 40b5a3b72..b169bd959 100644 --- a/src/video/win32/SDL_win32video.c +++ b/src/video/win32/SDL_win32video.c @@ -163,7 +163,7 @@ WIN_CreateDevice(int devindex) device->GL_DeleteContext = WIN_GL_DeleteContext; #endif device->StartTextInput = WIN_StartTextInput; - device->StopTextInput = WIN_StartTextInput; + device->StopTextInput = WIN_StopTextInput; device->SetTextInputRect = WIN_SetTextInputRect; device->free = WIN_DeleteDevice; From 3910703f2065b2b57cb6edaeb1b1210661d2bd6e Mon Sep 17 00:00:00 2001 From: dewyatt Date: Sat, 10 Jul 2010 13:15:47 -0400 Subject: [PATCH 21/24] Changed StopTextInput to take an SDL_Window parameter. --- include/SDL_keyboard.h | 2 +- src/SDL_compat.c | 2 +- src/video/SDL_sysvideo.h | 2 +- src/video/SDL_video.c | 4 ++-- src/video/win32/SDL_win32keyboard.c | 2 +- src/video/win32/SDL_win32keyboard.h | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/SDL_keyboard.h b/include/SDL_keyboard.h index fca34506f..cccafd001 100644 --- a/include/SDL_keyboard.h +++ b/include/SDL_keyboard.h @@ -147,7 +147,7 @@ extern DECLSPEC void SDLCALL SDL_StartTextInput(SDL_Window *window); * * \sa SDL_StartTextInput() */ -extern DECLSPEC void SDLCALL SDL_StopTextInput(void); +extern DECLSPEC void SDLCALL SDL_StopTextInput(SDL_Window *window); /** * \brief Set the rectangle used to type Unicode text inputs. diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 51b9b5ceb..112510598 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -1744,7 +1744,7 @@ SDL_EnableUNICODE(int enable) break; case 0: SDL_enabled_UNICODE = 0; - SDL_StopTextInput(); + SDL_StopTextInput(SDL_VideoWindow); break; } return previous; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 69ecb440d..7d93428f1 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -300,7 +300,7 @@ struct SDL_VideoDevice /* Text input */ void (*StartTextInput) (_THIS, SDL_Window *window); - void (*StopTextInput) (_THIS); + void (*StopTextInput) (_THIS, SDL_Window *window); void (*SetTextInputRect) (_THIS, SDL_Rect *rect); /* * * */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 744defea4..8e10ede43 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -3395,10 +3395,10 @@ SDL_StartTextInput(SDL_Window *window) } void -SDL_StopTextInput(void) +SDL_StopTextInput(SDL_Window *window) { if (_this && _this->StopTextInput) { - _this->StopTextInput(_this); + _this->StopTextInput(_this, window); } SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE); SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE); diff --git a/src/video/win32/SDL_win32keyboard.c b/src/video/win32/SDL_win32keyboard.c index 4ee297be7..3f2c4055f 100644 --- a/src/video/win32/SDL_win32keyboard.c +++ b/src/video/win32/SDL_win32keyboard.c @@ -130,7 +130,7 @@ WIN_StartTextInput(_THIS, SDL_Window *window) } void -WIN_StopTextInput(_THIS) +WIN_StopTextInput(_THIS, SDL_Window *window) { } diff --git a/src/video/win32/SDL_win32keyboard.h b/src/video/win32/SDL_win32keyboard.h index d9e54b3bd..dd3b3610d 100644 --- a/src/video/win32/SDL_win32keyboard.h +++ b/src/video/win32/SDL_win32keyboard.h @@ -32,7 +32,7 @@ extern void WIN_UpdateKeymap(void); extern void WIN_QuitKeyboard(_THIS); extern void WIN_StartTextInput(_THIS, SDL_Window *window); -extern void WIN_StopTextInput(_THIS); +extern void WIN_StopTextInput(_THIS, SDL_Window *window); extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect); #endif /* _SDL_win32keyboard_h */ From 53fe014899cac89c5edf7ac037f29d7b354905b2 Mon Sep 17 00:00:00 2001 From: dewyatt Date: Mon, 12 Jul 2010 11:33:27 -0400 Subject: [PATCH 22/24] Initial IMM implementation. IME input should now work fairly well. --- src/video/win32/SDL_win32events.c | 2 + src/video/win32/SDL_win32keyboard.c | 186 +++++++++++++++++++++++++++- src/video/win32/SDL_win32keyboard.h | 2 + src/video/win32/SDL_win32video.h | 10 ++ 4 files changed, 197 insertions(+), 3 deletions(-) diff --git a/src/video/win32/SDL_win32events.c b/src/video/win32/SDL_win32events.c index 185acc1f6..acbb0b497 100644 --- a/src/video/win32/SDL_win32events.c +++ b/src/video/win32/SDL_win32events.c @@ -131,6 +131,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } #endif + if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata)) + return 0; switch (msg) { diff --git a/src/video/win32/SDL_win32keyboard.c b/src/video/win32/SDL_win32keyboard.c index 3f2c4055f..c5de9dcc0 100644 --- a/src/video/win32/SDL_win32keyboard.c +++ b/src/video/win32/SDL_win32keyboard.c @@ -26,6 +26,9 @@ #include "../../events/SDL_keyboard_c.h" #include "../../events/scancodes_win32.h" +#include +#include + #ifndef MAPVK_VK_TO_VSC #define MAPVK_VK_TO_VSC 0 #endif @@ -46,6 +49,11 @@ BYTE keypad_scancodes[10] = { 82, 79, 80, 81, 75, 76, 77, 71, 72, 73 }; +void IME_Disable(SDL_VideoData *videodata, HWND hwnd); +void IME_Enable(SDL_VideoData *videodata, HWND hwnd); +void IME_Init(SDL_VideoData *videodata, HWND hwnd); +void IME_Quit(SDL_VideoData *videodata); + void WIN_InitKeyboard(_THIS) { @@ -81,6 +89,15 @@ WIN_InitKeyboard(_THIS) data->key_layout = win32_scancode_table; + data->ime_com_initialized = SDL_FALSE; + data->ime_thread_mgr = 0; + data->ime_initialized = SDL_FALSE; + data->ime_enabled = SDL_FALSE; + data->ime_available = SDL_FALSE; + data->ime_hwnd_main = 0; + data->ime_hwnd_current = 0; + data->ime_himc = 0; + WIN_UpdateKeymap(); SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu"); @@ -120,19 +137,25 @@ WIN_UpdateKeymap() void WIN_QuitKeyboard(_THIS) { + IME_Quit((SDL_VideoData *)_this->driverdata); } void WIN_StartTextInput(_THIS, SDL_Window *window) { - HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; - + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + IME_Init(videodata, hwnd); + IME_Enable(videodata, hwnd); } void WIN_StopTextInput(_THIS, SDL_Window *window) { - + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + IME_Init(videodata, hwnd); + IME_Disable(videodata, hwnd); } void @@ -141,4 +164,161 @@ WIN_SetTextInputRect(_THIS, SDL_Rect *rect) } +void +IME_Disable(SDL_VideoData *videodata, HWND hwnd) +{ + if (!videodata->ime_initialized || !videodata->ime_hwnd_current) + return; + + if (videodata->ime_hwnd_current == videodata->ime_hwnd_main) + ImmAssociateContext(videodata->ime_hwnd_current, NULL); + + videodata->ime_enabled = SDL_FALSE; +} + +void +IME_Enable(SDL_VideoData *videodata, HWND hwnd) +{ + if (!videodata->ime_initialized || !videodata->ime_hwnd_current) + return; + + if (!videodata->ime_available) { + IME_Disable(videodata, hwnd); + return; + } + if (videodata->ime_hwnd_current == videodata->ime_hwnd_main) + ImmAssociateContext(videodata->ime_hwnd_current, videodata->ime_himc); + + videodata->ime_enabled = SDL_TRUE; +} + +void +IME_Init(SDL_VideoData *videodata, HWND hwnd) +{ + if (videodata->ime_initialized) + return; + + videodata->ime_hwnd_main = hwnd; + if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { + videodata->ime_com_initialized = SDL_TRUE; + CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, &videodata->ime_thread_mgr); + } + videodata->ime_initialized = SDL_TRUE; + videodata->ime_hwnd_current = videodata->ime_hwnd_main; + if (videodata->ime_thread_mgr) { + struct ITfDocumentMgr *document_mgr = 0; + if (SUCCEEDED(videodata->ime_thread_mgr->lpVtbl->AssociateFocus(videodata->ime_thread_mgr, hwnd, NULL, &document_mgr))) { + if (document_mgr) + document_mgr->lpVtbl->Release(document_mgr); + } + } + videodata->ime_himc = ImmGetContext(hwnd); + ImmReleaseContext(hwnd, videodata->ime_himc); + if (!videodata->ime_himc) { + videodata->ime_available = SDL_FALSE; + IME_Disable(videodata, hwnd); + return; + } + videodata->ime_available = SDL_TRUE; + IME_Disable(videodata, hwnd); +} + +void +IME_Quit(SDL_VideoData *videodata) +{ + if (!videodata->ime_initialized) + return; + + if (videodata->ime_hwnd_main) + ImmAssociateContext(videodata->ime_hwnd_main, videodata->ime_himc); + + videodata->ime_hwnd_main = 0; + videodata->ime_himc = 0; + if (videodata->ime_thread_mgr) + { + videodata->ime_thread_mgr->lpVtbl->Release(videodata->ime_thread_mgr); + videodata->ime_thread_mgr = 0; + } + if (videodata->ime_com_initialized) + { + CoUninitialize(); + videodata->ime_com_initialized = SDL_FALSE; + } + videodata->ime_initialized = SDL_FALSE; +} + +SDL_bool +IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata) +{ + SDL_bool trap = SDL_FALSE; + HIMC himc = 0; + WCHAR Buffer[SDL_TEXTINPUTEVENT_TEXT_SIZE / 2]; + if (!videodata->ime_initialized || !videodata->ime_available || !videodata->ime_enabled) + return SDL_FALSE; + + switch (msg) + { + case WM_INPUTLANGCHANGE: + break; + case WM_IME_SETCONTEXT: + *lParam = 0; + break; + case WM_IME_STARTCOMPOSITION: + trap = SDL_TRUE; + break; + case WM_IME_COMPOSITION: + trap = SDL_TRUE; + himc = ImmGetContext(hwnd); + if (*lParam & GCS_RESULTSTR) + { + LONG Length = 0; + char *s = 0; + Length = ImmGetCompositionStringW(himc, GCS_RESULTSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0])); + Buffer[Length / sizeof(Buffer[0])] = 0; + s = WIN_StringToUTF8(Buffer); + SDL_SendKeyboardText(s); + SDL_free(s); + } + if (*lParam & GCS_COMPSTR) + { + LONG Length = 0; + DWORD Cursor = 0; + char *s = 0; + Length = ImmGetCompositionStringW(himc, GCS_COMPSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0])); + Buffer[Length / sizeof(Buffer[0])] = 0; + s = WIN_StringToUTF8(Buffer); + Cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0)); + SDL_SendEditingText(s, Cursor, 0); + SDL_free(s); + } + ImmReleaseContext(hwnd, himc); + break; + case WM_IME_ENDCOMPOSITION: + SDL_SendKeyboardText(""); + break; + case WM_IME_NOTIFY: + switch (wParam) + { + case IMN_SETCONVERSIONMODE: + break; + case IMN_SETOPENSTATUS: + break; + case IMN_OPENCANDIDATE: + case IMN_CHANGECANDIDATE: + trap = SDL_TRUE; + break; + case IMN_CLOSECANDIDATE: + trap = SDL_TRUE; + break; + case IMN_PRIVATE: + break; + default: + trap = SDL_TRUE; + break; + } + break; + } + return trap; +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32keyboard.h b/src/video/win32/SDL_win32keyboard.h index dd3b3610d..b2acc0165 100644 --- a/src/video/win32/SDL_win32keyboard.h +++ b/src/video/win32/SDL_win32keyboard.h @@ -35,6 +35,8 @@ extern void WIN_StartTextInput(_THIS, SDL_Window *window); extern void WIN_StopTextInput(_THIS, SDL_Window *window); extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect); +extern SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata); + #endif /* _SDL_win32keyboard_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32video.h b/src/video/win32/SDL_win32video.h index 3cfb63219..4d427f0cb 100644 --- a/src/video/win32/SDL_win32video.h +++ b/src/video/win32/SDL_win32video.h @@ -75,6 +75,16 @@ typedef struct SDL_VideoData #endif const SDL_scancode *key_layout; + + SDL_bool ime_com_initialized; + struct ITfThreadMgr *ime_thread_mgr; + SDL_bool ime_initialized; + SDL_bool ime_enabled; + SDL_bool ime_available; + HWND ime_hwnd_main; + HWND ime_hwnd_current; + HIMC ime_himc; + } SDL_VideoData; #endif /* _SDL_win32video_h */ From 50e06e6598ee117643be3b4a93d535b61d8da3ab Mon Sep 17 00:00:00 2001 From: dewyatt Date: Mon, 12 Jul 2010 14:17:43 -0400 Subject: [PATCH 23/24] Changed Start/StopTextInput back to not take any parameters. We call SDL_GetKeyboardFocus internally now. --- include/SDL_keyboard.h | 4 ++-- src/SDL_compat.c | 4 ++-- src/events/SDL_keyboard.c | 2 +- src/video/SDL_sysvideo.h | 4 ++-- src/video/SDL_video.c | 8 ++++---- src/video/win32/SDL_win32keyboard.c | 28 ++++++++++++++++++---------- src/video/win32/SDL_win32keyboard.h | 4 ++-- 7 files changed, 31 insertions(+), 23 deletions(-) diff --git a/include/SDL_keyboard.h b/include/SDL_keyboard.h index cccafd001..4482ac028 100644 --- a/include/SDL_keyboard.h +++ b/include/SDL_keyboard.h @@ -140,14 +140,14 @@ extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDLKey key); * \sa SDL_StopTextInput() * \sa SDL_SetTextInputRect() */ -extern DECLSPEC void SDLCALL SDL_StartTextInput(SDL_Window *window); +extern DECLSPEC void SDLCALL SDL_StartTextInput(void); /** * \brief Stop receiving any text input events. * * \sa SDL_StartTextInput() */ -extern DECLSPEC void SDLCALL SDL_StopTextInput(SDL_Window *window); +extern DECLSPEC void SDLCALL SDL_StopTextInput(void); /** * \brief Set the rectangle used to type Unicode text inputs. diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 112510598..bb8e46ba8 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -1740,11 +1740,11 @@ SDL_EnableUNICODE(int enable) switch (enable) { case 1: SDL_enabled_UNICODE = 1; - SDL_StartTextInput(SDL_VideoWindow); + SDL_StartTextInput(); break; case 0: SDL_enabled_UNICODE = 0; - SDL_StopTextInput(SDL_VideoWindow); + SDL_StopTextInput(); break; } return previous; diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 5de1116e3..f25bc6af8 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -617,7 +617,7 @@ SDL_SetKeyboardFocus(SDL_Window * window) 0, 0); if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) { - SDL_StartTextInput(window); + SDL_StartTextInput(); } } } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 7d93428f1..0a82717ec 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -299,8 +299,8 @@ struct SDL_VideoDevice void (*SuspendScreenSaver) (_THIS); /* Text input */ - void (*StartTextInput) (_THIS, SDL_Window *window); - void (*StopTextInput) (_THIS, SDL_Window *window); + void (*StartTextInput) (_THIS); + void (*StopTextInput) (_THIS); void (*SetTextInputRect) (_THIS, SDL_Rect *rect); /* * * */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 8e10ede43..db8b5d3cb 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -3385,20 +3385,20 @@ SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info) } void -SDL_StartTextInput(SDL_Window *window) +SDL_StartTextInput(void) { if (_this && _this->StartTextInput) { - _this->StartTextInput(_this, window); + _this->StartTextInput(_this); } SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE); SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE); } void -SDL_StopTextInput(SDL_Window *window) +SDL_StopTextInput(void) { if (_this && _this->StopTextInput) { - _this->StopTextInput(_this, window); + _this->StopTextInput(_this); } SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE); SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE); diff --git a/src/video/win32/SDL_win32keyboard.c b/src/video/win32/SDL_win32keyboard.c index c5de9dcc0..23caa2d28 100644 --- a/src/video/win32/SDL_win32keyboard.c +++ b/src/video/win32/SDL_win32keyboard.c @@ -141,21 +141,29 @@ WIN_QuitKeyboard(_THIS) } void -WIN_StartTextInput(_THIS, SDL_Window *window) +WIN_StartTextInput(_THIS) { - HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; - SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; - IME_Init(videodata, hwnd); - IME_Enable(videodata, hwnd); + SDL_Window *window = SDL_GetKeyboardFocus(); + if (window) + { + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + IME_Init(videodata, hwnd); + IME_Enable(videodata, hwnd); + } } void -WIN_StopTextInput(_THIS, SDL_Window *window) +WIN_StopTextInput(_THIS) { - HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; - SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; - IME_Init(videodata, hwnd); - IME_Disable(videodata, hwnd); + SDL_Window *window = SDL_GetKeyboardFocus(); + if (window) + { + HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; + IME_Init(videodata, hwnd); + IME_Disable(videodata, hwnd); + } } void diff --git a/src/video/win32/SDL_win32keyboard.h b/src/video/win32/SDL_win32keyboard.h index b2acc0165..670730bba 100644 --- a/src/video/win32/SDL_win32keyboard.h +++ b/src/video/win32/SDL_win32keyboard.h @@ -31,8 +31,8 @@ extern void WIN_InitKeyboard(_THIS); extern void WIN_UpdateKeymap(void); extern void WIN_QuitKeyboard(_THIS); -extern void WIN_StartTextInput(_THIS, SDL_Window *window); -extern void WIN_StopTextInput(_THIS, SDL_Window *window); +extern void WIN_StartTextInput(_THIS); +extern void WIN_StopTextInput(_THIS); extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect); extern SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata); From 16f4b7cae4f73956caa965340594ef8e66c8432e Mon Sep 17 00:00:00 2001 From: dewyatt Date: Tue, 13 Jul 2010 15:05:45 -0400 Subject: [PATCH 24/24] Added SDL_utf8strlcpy to copy at UTF-8 character boundaries. Changed SDL_SendKeyboardText and SDL_SendEditingText to use SDL_utf8strlcpy. --- include/SDL_stdinc.h | 3 +++ src/events/SDL_keyboard.c | 4 ++-- src/stdlib/SDL_string.c | 47 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h index c7e7edd57..fb143acb5 100644 --- a/include/SDL_stdinc.h +++ b/include/SDL_stdinc.h @@ -470,6 +470,9 @@ extern DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen); #endif +extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(char *dst, const char *src, + size_t dst_bytes); + #ifdef HAVE_STRLCAT #define SDL_strlcat strlcat #else diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index f25bc6af8..f56075eaa 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -766,7 +766,7 @@ SDL_SendKeyboardText(const char *text) SDL_Event event; event.text.type = SDL_TEXTINPUT; event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; - SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text)); + SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text)); event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } @@ -787,7 +787,7 @@ SDL_SendEditingText(const char *text, int start, int length) event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; event.edit.start = start; event.edit.length = length; - SDL_strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text)); + SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text)); posted = (SDL_PushEvent(&event) > 0); } return (posted); diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index d70f8666a..b6839c1cf 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -29,6 +29,21 @@ #define SDL_isupperhex(X) (((X) >= 'A') && ((X) <= 'F')) #define SDL_islowerhex(X) (((X) >= 'a') && ((X) <= 'f')) +#define UTF8_IsLeadByte(c) ((c) >= 0xC0 && (c) <= 0xF4) +#define UTF8_IsTrailingByte(c) ((c) >= 0x80 && (c) <= 0xBF) + +int UTF8_TrailingBytes(unsigned char c) +{ + if (c >= 0xC0 && c<= 0xDF) + return 1; + else if (c >= 0xE0 && c <= 0xEF) + return 2; + else if (c >= 0xF0 && c <= 0xF4) + return 3; + else + return 0; +} + #if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL) static size_t SDL_ScanLong(const char *text, int radix, long *valuep) @@ -362,6 +377,38 @@ SDL_strlcpy(char *dst, const char *src, size_t maxlen) } #endif +size_t SDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes) +{ + size_t src_bytes = SDL_strlen(src); + size_t bytes = SDL_min(src_bytes, dst_bytes - 1); + int i = 0; + char trailing_bytes = 0; + if (bytes) + { + unsigned char c = (unsigned char)src[bytes - 1]; + if (UTF8_IsLeadByte(c)) + --bytes; + else if (UTF8_IsTrailingByte(c)) + { + for (i = bytes - 1; i != 0; --i) + { + c = (unsigned char)src[i]; + trailing_bytes = UTF8_TrailingBytes(c); + if (trailing_bytes) + { + if (bytes - i != trailing_bytes + 1) + bytes = i; + + break; + } + } + } + SDL_memcpy(dst, src, bytes); + } + dst[bytes] = '\0'; + return bytes; +} + #ifndef HAVE_STRLCAT size_t SDL_strlcat(char *dst, const char *src, size_t maxlen)