aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-10-21 22:15:52 +0800
committercrupest <crupest@outlook.com>2021-10-21 22:15:52 +0800
commite998a88b5ad6cc260836b3374e882e2ef67d5d35 (patch)
tree0bf82250bae0817370986a9a20750bae92a4922f
parent6f1edc1604341b32e13371c8a4ad431e9a00cc87 (diff)
downloadcru-e998a88b5ad6cc260836b3374e882e2ef67d5d35.tar.gz
cru-e998a88b5ad6cc260836b3374e882e2ef67d5d35.tar.bz2
cru-e998a88b5ad6cc260836b3374e882e2ef67d5d35.zip
...
-rw-r--r--demos/input_method/main.cpp18
-rw-r--r--include/cru/osx/gui/InputMethod.hpp1
-rw-r--r--src/osx/gui/InputMethod.mm88
-rw-r--r--src/osx/gui/InputMethodPrivate.h22
-rw-r--r--src/osx/gui/Window.mm131
-rw-r--r--src/osx/gui/WindowPrivate.h4
6 files changed, 131 insertions, 133 deletions
diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp
index dc2e0858..cc86ce4d 100644
--- a/demos/input_method/main.cpp
+++ b/demos/input_method/main.cpp
@@ -37,10 +37,10 @@ int main() {
auto prompt_text_layout =
graphics_factory->CreateTextLayout(font,
- u"Alt+F1: Enable IME\n"
- u"Alt+F2: Disable IME\n"
- u"Alt+F3: Complete composition.\n"
- u"Alt+F4: Cancel composition.");
+ u"Ctrl+1: Enable IME\n"
+ u"Ctrl+2: Disable IME\n"
+ u"Ctrl+3: Complete composition.\n"
+ u"Ctrl+4: Cancel composition.");
std::optional<CompositionText> optional_composition_text;
String committed_text;
@@ -102,18 +102,18 @@ int main() {
window->KeyDownEvent()->AddHandler(
[&input_method_context](const NativeKeyEventArgs& args) {
- if (args.modifier & KeyModifiers::alt) {
+ if (args.modifier & KeyModifiers::ctrl) {
switch (args.key) {
- case KeyCode::F1:
+ case KeyCode::N1:
input_method_context->EnableIME();
break;
- case KeyCode::F2:
+ case KeyCode::N2:
input_method_context->DisableIME();
break;
- case KeyCode::F3:
+ case KeyCode::N3:
input_method_context->CompleteComposition();
break;
- case KeyCode::F4:
+ case KeyCode::N4:
input_method_context->CancelComposition();
break;
default:
diff --git a/include/cru/osx/gui/InputMethod.hpp b/include/cru/osx/gui/InputMethod.hpp
index 79f06f36..6528ce57 100644
--- a/include/cru/osx/gui/InputMethod.hpp
+++ b/include/cru/osx/gui/InputMethod.hpp
@@ -12,6 +12,7 @@ class OsxInputMethodContextPrivate;
class OsxInputMethodContext : public OsxGuiResource,
public virtual IInputMethodContext {
+ friend OsxWindow;
friend details::OsxInputMethodContextPrivate;
public:
diff --git a/src/osx/gui/InputMethod.mm b/src/osx/gui/InputMethod.mm
index 2c4ac643..ec8d194c 100644
--- a/src/osx/gui/InputMethod.mm
+++ b/src/osx/gui/InputMethod.mm
@@ -7,8 +7,6 @@
#include "cru/osx/Convert.hpp"
#include "cru/osx/gui/Window.hpp"
-using cru::platform::osx::Convert;
-
namespace cru::platform::gui::osx {
namespace details {
OsxInputMethodContextPrivate::OsxInputMethodContextPrivate(
@@ -34,14 +32,12 @@ void OsxInputMethodContextPrivate::PerformSel(SEL sel) {
}
void OsxInputMethodContextPrivate::Activate() {
- if (!window_->p_->GetNSWindow()) return;
auto input_context = [[window_->p_->GetNSWindow() contentView] inputContext];
Ensures(input_context);
[input_context activate];
}
void OsxInputMethodContextPrivate::Deactivate() {
- if (!window_->p_->GetNSWindow()) return;
auto input_context = [[window_->p_->GetNSWindow() contentView] inputContext];
Ensures(input_context);
[input_context deactivate];
@@ -95,87 +91,3 @@ IEvent<std::nullptr_t>* OsxInputMethodContext::CompositionEvent() {
IEvent<StringView>* OsxInputMethodContext::TextEvent() { return &p_->text_event_; }
}
-
-@implementation CruInputClient {
- cru::platform::gui::osx::details::OsxInputMethodContextPrivate* _p;
- NSMutableAttributedString* _text;
-}
-
-- (id)init:(cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)p {
- _p = p;
- return self;
-}
-
-- (BOOL)hasMarkedText {
- return _text != nil;
-}
-
-- (NSRange)markedRange {
- return _text == nil ? NSRange{NSNotFound, 0} : NSRange{0, [_text length]};
-}
-
-- (NSRange)selectedRange {
- return NSMakeRange(_p->GetSelectionRange().position, _p->GetSelectionRange().count);
-}
-
-- (void)setMarkedText:(id)string
- selectedRange:(NSRange)selectedRange
- replacementRange:(NSRange)replacementRange {
- if (_text == nil) {
- _text = [[NSMutableAttributedString alloc] init];
- _p->RaiseCompositionStartEvent();
- }
-
- [_text deleteCharactersInRange:replacementRange];
- [_text insertAttributedString:[[NSAttributedString alloc] initWithString:(NSString*)string]
- atIndex:replacementRange.location];
-
- cru::platform::gui::CompositionText composition_text;
- composition_text.text = Convert((CFStringRef)[_text string]);
- composition_text.selection.position = replacementRange.location + selectedRange.location;
- composition_text.selection.count = selectedRange.length;
- _p->SetCompositionText(composition_text);
- _p->RaiseCompositionEvent();
-}
-
-- (void)unmarkText {
- _text = nil;
- _p->RaiseCompositionEndEvent();
-}
-
-- (NSArray<NSAttributedStringKey>*)validAttributesForMarkedText {
- return @[
- (NSString*)kCTUnderlineColorAttributeName, (NSString*)kCTUnderlineStyleAttributeName,
- (NSString*)kCTForegroundColorAttributeName, (NSString*)kCTBackgroundColorAttributeName
- ];
-}
-
-- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
- actualRange:(NSRangePointer)actualRange {
- return [_text attributedSubstringFromRange:range];
-}
-
-- (void)insertText:(id)string replacementRange:(NSRange)replacementRange {
- _text = nil;
- cru::String s = Convert((CFStringRef)string);
- _p->RaiseCompositionEndEvent();
- _p->RaiseTextEvent(s);
-}
-
-- (NSUInteger)characterIndexForPoint:(NSPoint)point {
- return NSNotFound;
-}
-
-- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
- NSRect result;
- result.origin.x = _p->GetCandidateWindowPosition().x;
- result.origin.y = _p->GetCandidateWindowPosition().y;
- result.size.height = 16;
- result.size.width = 0;
- return result;
-}
-
-- (void)doCommandBySelector:(SEL)selector {
- _p->PerformSel(selector);
-}
-@end
diff --git a/src/osx/gui/InputMethodPrivate.h b/src/osx/gui/InputMethodPrivate.h
index 4b5478e1..d2fccb43 100644
--- a/src/osx/gui/InputMethodPrivate.h
+++ b/src/osx/gui/InputMethodPrivate.h
@@ -1,11 +1,7 @@
#pragma once
#include "cru/osx/gui/InputMethod.hpp"
-#import <AppKit/AppKit.h>
-
-@interface CruInputClient : NSObject <NSTextInputClient>
-- (id)init:(cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)p;
-@end
+#include <AppKit/AppKit.h>
namespace cru::platform::gui::osx {
namespace details {
@@ -13,7 +9,8 @@ class OsxInputMethodContextPrivate {
friend OsxInputMethodContext;
public:
- OsxInputMethodContextPrivate(OsxInputMethodContext* input_method_context, OsxWindow* window);
+ OsxInputMethodContextPrivate(OsxInputMethodContext* input_method_context,
+ OsxWindow* window);
CRU_DELETE_COPY(OsxInputMethodContextPrivate)
CRU_DELETE_MOVE(OsxInputMethodContextPrivate)
@@ -30,10 +27,14 @@ class OsxInputMethodContextPrivate {
void RaiseTextEvent(StringView text);
Point GetCandidateWindowPosition() const { return candidate_window_point_; }
- void SetCandidateWindowPosition(const Point& p) { candidate_window_point_ = p; }
+ void SetCandidateWindowPosition(const Point& p) {
+ candidate_window_point_ = p;
+ }
Range GetSelectionRange() const { return selection_range_; }
- void SetSelectionRange(Range selection_range) { selection_range_ = selection_range; }
+ void SetSelectionRange(Range selection_range) {
+ selection_range_ = selection_range;
+ }
void PerformSel(SEL sel);
@@ -57,6 +58,5 @@ class OsxInputMethodContextPrivate {
Event<std::nullptr_t> composition_end_event_;
Event<StringView> text_event_;
};
-
-}
-}
+} // namespace details
+} // namespace cru::platform::gui::osx
diff --git a/src/osx/gui/Window.mm b/src/osx/gui/Window.mm
index 8e21518e..136c3064 100644
--- a/src/osx/gui/Window.mm
+++ b/src/osx/gui/Window.mm
@@ -2,6 +2,7 @@
#include "WindowPrivate.h"
#include "CursorPrivate.h"
+#include "InputMethodPrivate.h"
#include "cru/common/Logger.hpp"
#include "cru/common/Range.hpp"
#include "cru/osx/Convert.hpp"
@@ -30,6 +31,7 @@
#include <limits>
#include <memory>
+using cru::platform::osx::Convert;
using cru::platform::graphics::osx::quartz::Convert;
namespace cru::platform::gui::osx {
@@ -225,6 +227,7 @@ void OsxWindow::CreateWindow() {
[p_->window_ setDelegate:p_->window_delegate_];
NSView* content_view = [[CruView alloc] init:p_.get()
+ input_context_p:p_->input_method_context_->p_.get()
frame:Rect(Point{}, p_->content_rect_.GetSize())];
[p_->window_ setContentView:content_view];
@@ -290,16 +293,54 @@ IInputMethodContext* OsxWindow::GetInputMethodContext() { return p_->input_metho
- (BOOL)canBecomeKeyWindow {
return YES;
}
+
+- (void)keyDown:(NSEvent*)event {
+ cru::log::TagDebug(u"CruWindow", u"Recieved key down.");
+
+ cru::platform::gui::KeyModifier key_modifier;
+ if (event.modifierFlags & NSEventModifierFlagControl)
+ key_modifier |= cru::platform::gui::KeyModifiers::ctrl;
+ if (event.modifierFlags & NSEventModifierFlagOption)
+ key_modifier |= cru::platform::gui::KeyModifiers::alt;
+ if (event.modifierFlags & NSEventModifierFlagShift)
+ key_modifier |= cru::platform::gui::KeyModifiers::shift;
+ auto c = cru::platform::gui::osx::KeyCodeFromOsxToCru(event.keyCode);
+
+ _p->OnKeyDown(c, key_modifier);
+
+ [super keyDown:event];
+}
+
+- (void)keyUp:(NSEvent*)event {
+ cru::log::TagDebug(u"CruWindow", u"Recieved key up.");
+
+ cru::platform::gui::KeyModifier key_modifier;
+ if (event.modifierFlags & NSEventModifierFlagControl)
+ key_modifier |= cru::platform::gui::KeyModifiers::ctrl;
+ if (event.modifierFlags & NSEventModifierFlagOption)
+ key_modifier |= cru::platform::gui::KeyModifiers::alt;
+ if (event.modifierFlags & NSEventModifierFlagShift)
+ key_modifier |= cru::platform::gui::KeyModifiers::shift;
+ auto c = cru::platform::gui::osx::KeyCodeFromOsxToCru(event.keyCode);
+
+ _p->OnKeyUp(c, key_modifier);
+ [super keyUp:event];
+}
@end
@implementation CruView {
cru::platform::gui::osx::details::OsxWindowPrivate* _p;
+ cru::platform::gui::osx::details::OsxInputMethodContextPrivate* _input_context_p;
+ NSMutableAttributedString* _input_context_text;
}
- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p
+ input_context_p:
+ (cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)input_context_p
frame:(cru::platform::Rect)frame {
[super initWithFrame:cru::platform::graphics::osx::quartz::Convert(frame)];
_p = p;
+ _input_context_p = input_context_p;
auto tracking_area = [[NSTrackingArea alloc]
initWithRect:Convert(frame)
@@ -418,38 +459,80 @@ IInputMethodContext* OsxWindow::GetInputMethodContext() { return p_->input_metho
_p->OnMouseWheel(static_cast<float>(event.scrollingDeltaY), p, key_modifier);
}
-- (void)keyDown:(NSEvent*)event {
- cru::log::TagDebug(u"CruView", u"Recieved key down.");
+- (BOOL)hasMarkedText {
+ return _input_context_text != nil;
+}
- cru::platform::gui::KeyModifier key_modifier;
- if (event.modifierFlags & NSEventModifierFlagControl)
- key_modifier |= cru::platform::gui::KeyModifiers::ctrl;
- if (event.modifierFlags & NSEventModifierFlagOption)
- key_modifier |= cru::platform::gui::KeyModifiers::alt;
- if (event.modifierFlags & NSEventModifierFlagShift)
- key_modifier |= cru::platform::gui::KeyModifiers::shift;
- auto c = cru::platform::gui::osx::KeyCodeFromOsxToCru(event.keyCode);
+- (NSRange)markedRange {
+ return _input_context_text == nil ? NSRange{NSNotFound, 0}
+ : NSRange{0, [_input_context_text length]};
+}
- _p->OnKeyDown(c, key_modifier);
+- (NSRange)selectedRange {
+ return NSMakeRange(_input_context_p->GetSelectionRange().position,
+ _input_context_p->GetSelectionRange().count);
+}
- [super keyDown:event];
+- (void)setMarkedText:(id)string
+ selectedRange:(NSRange)selectedRange
+ replacementRange:(NSRange)replacementRange {
+ if (_input_context_text == nil) {
+ _input_context_text = [[NSMutableAttributedString alloc] init];
+ _input_context_p->RaiseCompositionStartEvent();
+ }
+
+ [_input_context_text deleteCharactersInRange:replacementRange];
+ [_input_context_text
+ insertAttributedString:[[NSAttributedString alloc] initWithString:(NSString*)string]
+ atIndex:replacementRange.location];
+
+ cru::platform::gui::CompositionText composition_text;
+ composition_text.text = Convert((CFStringRef)[_input_context_text string]);
+ composition_text.selection.position = replacementRange.location + selectedRange.location;
+ composition_text.selection.count = selectedRange.length;
+ _input_context_p->SetCompositionText(composition_text);
+ _input_context_p->RaiseCompositionEvent();
}
-- (void)keyUp:(NSEvent*)event {
- cru::log::TagDebug(u"CruView", u"Recieved key up.");
+- (void)unmarkText {
+ _input_context_text = nil;
+ _input_context_p->RaiseCompositionEndEvent();
+}
- cru::platform::gui::KeyModifier key_modifier;
- if (event.modifierFlags & NSEventModifierFlagControl)
- key_modifier |= cru::platform::gui::KeyModifiers::ctrl;
- if (event.modifierFlags & NSEventModifierFlagOption)
- key_modifier |= cru::platform::gui::KeyModifiers::alt;
- if (event.modifierFlags & NSEventModifierFlagShift)
- key_modifier |= cru::platform::gui::KeyModifiers::shift;
- auto c = cru::platform::gui::osx::KeyCodeFromOsxToCru(event.keyCode);
+- (NSArray<NSAttributedStringKey>*)validAttributesForMarkedText {
+ return @[
+ (NSString*)kCTUnderlineColorAttributeName, (NSString*)kCTUnderlineStyleAttributeName,
+ (NSString*)kCTForegroundColorAttributeName, (NSString*)kCTBackgroundColorAttributeName
+ ];
+}
- _p->OnKeyUp(c, key_modifier);
+- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
+ actualRange:(NSRangePointer)actualRange {
+ return [_input_context_text attributedSubstringFromRange:range];
+}
- [super keyUp:event];
+- (void)insertText:(id)string replacementRange:(NSRange)replacementRange {
+ _input_context_text = nil;
+ cru::String s = Convert((CFStringRef)string);
+ _input_context_p->RaiseCompositionEndEvent();
+ _input_context_p->RaiseTextEvent(s);
+}
+
+- (NSUInteger)characterIndexForPoint:(NSPoint)point {
+ return NSNotFound;
+}
+
+- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
+ NSRect result;
+ result.origin.x = _input_context_p->GetCandidateWindowPosition().x;
+ result.origin.y = _input_context_p->GetCandidateWindowPosition().y;
+ result.size.height = 16;
+ result.size.width = 0;
+ return result;
+}
+
+- (void)doCommandBySelector:(SEL)selector {
+ _input_context_p->PerformSel(selector);
}
@end
diff --git a/src/osx/gui/WindowPrivate.h b/src/osx/gui/WindowPrivate.h
index e3b93f8a..076b59d9 100644
--- a/src/osx/gui/WindowPrivate.h
+++ b/src/osx/gui/WindowPrivate.h
@@ -17,8 +17,10 @@
style:(NSWindowStyleMask)style;
@end
-@interface CruView : NSView
+@interface CruView : NSView <NSTextInputClient>
- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p
+ input_context_p:
+ (cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)input_context_p
frame:(cru::platform::Rect)frame;
@end