Skip to content

Commit 6b28b39

Browse files
authored
Added unicode input
Added unicode input
1 parent b7fa81f commit 6b28b39

File tree

3 files changed

+113
-25
lines changed

3 files changed

+113
-25
lines changed

egui-opengl-internal/src/app.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
use std::ffi::c_void;
1+
use std::ffi::{c_void, OsString};
22
use crate::{input::InputCollector, painter, utils};
33
use clipboard::{windows_clipboard::WindowsClipboardContext, ClipboardProvider};
4-
use egui::Context;
4+
use egui::{Context, FontData, FontDefinitions, FontFamily, FontId};
55
use once_cell::sync::OnceCell;
66
use std::ops::DerefMut;
7+
use std::path::PathBuf;
8+
use std::sync::Arc;
9+
use egui::FontFamily::Proportional;
10+
use egui::TextStyle::{Body, Button, Heading, Monospace, Name, Small};
711
use windows::Win32::{
812
Foundation::{HWND, LPARAM, RECT, WPARAM},
913
Graphics::{
@@ -31,6 +35,8 @@ use parking_lot::{Mutex, MutexGuard};
3135
use spin::lock_api::{Mutex, MutexGuard};
3236

3337
use lock_api::MappedMutexGuard;
38+
use windows::Win32::Foundation::HINSTANCE;
39+
use windows::Win32::UI::WindowsAndMessaging::{WM_CHAR, WM_UNICHAR};
3440

3541
/// Heart and soul of this integration.
3642
/// Main methods you are going to use are:
@@ -157,7 +163,41 @@ impl<T: Default> OpenGLApp<T> {
157163
/// Initializes application and sets the state to its default value. You should call this only once!
158164
#[inline]
159165
pub fn init_default(&self, hdc: HDC, window: HWND, ui: impl FnMut(&Context, &mut T) + 'static) {
160-
self.init_with_state_context(hdc, window, ui, T::default(), Context::default());
166+
let ctx = Context::default();
167+
168+
let font_file = {
169+
let mut font_path = PathBuf::from(std::env::var("SystemRoot").ok().unwrap());
170+
font_path.push("Fonts");
171+
font_path.push("arial.ttf");
172+
font_path.to_str().unwrap().to_string().replace("\\", "/")
173+
};
174+
let font_name = font_file.split('/').last().unwrap().split('.').next().unwrap().to_string();
175+
let font_file_bytes = std::fs::read(font_file).ok().unwrap();
176+
177+
let font_data = FontData::from_owned(font_file_bytes);
178+
let mut font_def = FontDefinitions::default();
179+
font_def.font_data.insert(font_name.to_string(), font_data);
180+
181+
let font_family = Proportional;
182+
font_def.families.get_mut(&font_family).unwrap().insert(0, font_name);
183+
184+
ctx.set_fonts(font_def);
185+
186+
187+
// Set custom sizes for text styles
188+
let mut style = (*ctx.style()).clone();
189+
style.text_styles = [
190+
(Heading, FontId::new(30.0, Proportional)),
191+
(Name("Heading2".into()), FontId::new(25.0, Proportional)),
192+
(Name("Context".into()), FontId::new(23.0, Proportional)),
193+
(Body, FontId::new(18.0, Proportional)),
194+
(Monospace, FontId::new(14.0, Proportional)),
195+
(Button, FontId::new(14.0, Proportional)),
196+
(Small, FontId::new(10.0, Proportional)),
197+
].into();
198+
199+
ctx.set_style(style);
200+
self.init_with_state_context(hdc, window, ui, T::default(), ctx);
161201
}
162202
}
163203

@@ -212,12 +252,17 @@ impl<T> OpenGLApp<T> {
212252
#[inline]
213253
pub fn wnd_proc(&self, umsg: u32, wparam: WPARAM, lparam: LPARAM) -> bool {
214254
let this = &mut *self.lock_data();
255+
256+
257+
215258
this.input_collector.process(umsg, wparam.0, lparam.0);
216259

217260
if umsg == WM_SIZE {
218261
this.client_rect = self.get_client_rect(this.window);
219262
}
220263

264+
265+
221266
this.ctx.wants_keyboard_input() || this.ctx.wants_pointer_input()
222267
}
223268

egui-opengl-internal/src/input.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use windows::Win32::{
1111
VK_RIGHT, VK_SPACE, VK_TAB, VK_UP,
1212
},
1313
WindowsAndMessaging::{
14-
GetClientRect, KF_REPEAT, WHEEL_DELTA, WM_CHAR, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDBLCLK,
14+
GetClientRect, KF_REPEAT, WHEEL_DELTA, WM_CHAR, WM_UNICHAR, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDBLCLK,
1515
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDBLCLK, WM_MBUTTONDOWN, WM_MBUTTONUP,
1616
WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDBLCLK, WM_RBUTTONDOWN,
1717
WM_RBUTTONUP, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_XBUTTONDBLCLK, WM_XBUTTONDOWN,
@@ -165,10 +165,37 @@ impl InputCollector {
165165
});
166166
InputResult::MouseMiddle
167167
}
168+
WM_UNICHAR => {
169+
// Handle Unicode characters from WM_UNICHAR
170+
let unicode_char = wparam as u32; // wparam is the Unicode character
171+
172+
// Debugging output
173+
println!("WM_UNICHAR received: unicode_char = {}", unicode_char);
174+
175+
if unicode_char != 0xFFFF { // 0xFFFF indicates no character
176+
if let Some(ch) = char::from_u32(unicode_char) {
177+
// Print the character representation
178+
println!("Character from WM_UNICHAR: '{}'", ch);
179+
if !ch.is_control() {
180+
self.events.push(Event::Text(ch.into())); // Add the character to events
181+
}
182+
} else {
183+
println!("Invalid character for unicode_char: {}", unicode_char);
184+
}
185+
}
186+
InputResult::Character
187+
}
188+
168189
WM_CHAR => {
169-
if let Some(ch) = char::from_u32(wparam as _) {
170-
if !ch.is_control() {
171-
self.events.push(Event::Text(ch.into()));
190+
// Handle characters from WM_CHAR
191+
let unicode_char = wparam as u32; // wparam is the character code
192+
if unicode_char != 0xFFFF { // 0xFFFF indicates no character
193+
if let Some(ch) = char::from_u32(unicode_char) {
194+
if !ch.is_control() {
195+
self.events.push(Event::Text(ch.into())); // Add the character to events
196+
}
197+
} else {
198+
println!("Invalid character for unicode_char: {}", unicode_char);
172199
}
173200
}
174201
InputResult::Character

example-wnd/src/lib.rs

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
1-
use egui::{Color32, Context, Key, Modifiers, RichText, ScrollArea, Slider, Widget};
2-
use egui_opengl_internal::{utils, OpenGLApp};
3-
use retour::static_detour;
41
use std::{intrinsics::transmute, sync::Once};
52
use std::ffi::c_void;
3+
use std::ops::DerefMut;
4+
use std::sync::{Arc, Mutex};
5+
6+
use egui::{Color32, Context, Key, Modifiers, RichText, ScrollArea, Slider, Widget};
7+
use once_cell::unsync::Lazy;
8+
use retour::static_detour;
69
use windows::{
710
core::HRESULT,
811
Win32::{
912
Foundation::{HWND, LPARAM, LRESULT, WPARAM},
10-
Graphics::Gdi::{WindowFromDC, HDC},
11-
UI::WindowsAndMessaging::{CallWindowProcW, SetWindowLongPtrA, GWLP_WNDPROC, WNDPROC},
13+
Graphics::Gdi::{HDC, WindowFromDC},
14+
UI::WindowsAndMessaging::{CallWindowProcW, GWLP_WNDPROC, WNDPROC},
1215
},
1316
};
1417
use windows::Win32::Foundation::{BOOL, TRUE};
18+
use windows::Win32::UI::WindowsAndMessaging::SetWindowLongPtrW;
1519

16-
use std::sync::{Arc, Mutex};
17-
use once_cell::unsync::Lazy;
20+
use egui_opengl_internal::{OpenGLApp, utils};
1821

1922
struct UIState {
2023
ui_check: bool,
21-
text: Option<String>,
24+
text: String,
2225
value: f32,
2326
color: [f32; 3],
2427
}
@@ -27,7 +30,7 @@ impl UIState {
2730
fn new() -> Self {
2831
Self {
2932
ui_check: true,
30-
text: Some(String::from("Test")),
33+
text: String::from("Test"),
3134
value: 0.0,
3235
color: [0.0, 0.0, 0.0],
3336
}
@@ -50,7 +53,7 @@ extern "system" fn DllMain(hinst: usize, reason: u32, _reserved: *mut c_void) ->
5053
let _: Option<WNDPROC> = Some(transmute::<i32,
5154
Option<unsafe extern "system"
5255
fn(HWND, u32, WPARAM, LPARAM) -> LRESULT>>(
53-
SetWindowLongPtrA(
56+
SetWindowLongPtrW(
5457
APP.get_window(),
5558
GWLP_WNDPROC,
5659
wnd_proc as usize as _,
@@ -85,15 +88,15 @@ fn hk_wgl_swap_buffers(hdc: HDC) -> HRESULT {
8588

8689
OLD_WND_PROC = Some(transmute::<i32, Option<unsafe extern "system"
8790
fn(HWND, u32, WPARAM, LPARAM) -> LRESULT>>(
88-
SetWindowLongPtrA(
91+
SetWindowLongPtrW(
8992
window,
9093
GWLP_WNDPROC,
9194
hk_wnd_proc as usize as _,
9295
)));
9396
});
9497

9598
if !APP.get_window().eq(&window) {
96-
SetWindowLongPtrA(window, GWLP_WNDPROC, hk_wnd_proc as usize as _);
99+
SetWindowLongPtrW(window, GWLP_WNDPROC, hk_wnd_proc as usize as _);
97100
}
98101

99102
APP.render(hdc);
@@ -137,7 +140,7 @@ unsafe fn main_thread(_hinst: usize) {
137140
utils::alloc_console();
138141

139142
let wgl_swap_buffers = utils::get_proc_address("wglSwapBuffers");
140-
let fn_wgl_swap_buffers: FnWglSwapBuffers = std::mem::transmute(wgl_swap_buffers);
143+
let fn_wgl_swap_buffers: FnWglSwapBuffers = transmute(wgl_swap_buffers);
141144

142145
println!("wglSwapBuffers: {:X}", wgl_swap_buffers as usize);
143146

@@ -153,7 +156,7 @@ unsafe fn main_thread(_hinst: usize) {
153156
}
154157

155158
unsafe fn test_ui(ctx: &Context, ui: &mut egui::Ui) {
156-
let mut state = STATE.lock().unwrap(); // Lock the state
159+
let state = STATE.as_ref();
157160

158161
// UI Elements
159162
ui.label(RichText::new("Test").color(Color32::LIGHT_BLUE));
@@ -178,8 +181,15 @@ unsafe fn test_ui(ctx: &Context, ui: &mut egui::Ui) {
178181
}
179182

180183
// Checkbox and Text Input
181-
ui.checkbox(&mut state.ui_check, "Some checkbox");
182-
ui.text_edit_singleline(state.text.as_mut().unwrap());
184+
let mut binding = state.lock().unwrap();
185+
let ui_state = binding.deref_mut();
186+
if ui.checkbox(&mut ui_state.ui_check, "Some checkbox").changed() {
187+
println!("Checkbox toggled to: {}", ui_state.ui_check);
188+
}
189+
if ui.text_edit_singleline(&mut ui_state.text).changed()
190+
{
191+
println!("Set edit singleline to: {}", ui_state.text);
192+
}
183193

184194
// Scroll Area
185195
ScrollArea::vertical().max_height(200.0).show(ui, |ui| {
@@ -189,10 +199,16 @@ unsafe fn test_ui(ctx: &Context, ui: &mut egui::Ui) {
189199
});
190200

191201
// Slider
192-
Slider::new(&mut state.value, -1.0..=1.0).ui(ui);
202+
if Slider::new(&mut ui_state.value, -1.0..=1.0).ui(ui).changed()
203+
{
204+
println!("Slider set value to: {}", ui_state.value);
205+
}
193206

194207
// Color Picker
195-
ui.color_edit_button_rgb(&mut state.color);
208+
if ui.color_edit_button_rgb(&mut ui_state.color).changed()
209+
{
210+
println!("Color edit button set color to: {:?}", ui_state.color);
211+
}
196212

197213
// Display Pointer Info
198214
ui.label(format!(

0 commit comments

Comments
 (0)