Ken Thomases : winemac: Improve positioning of input method candidate window.
Alexandre Julliard
julliard at winehq.org
Fri May 17 14:24:33 CDT 2013
Module: wine
Branch: master
Commit: 939d9a906ff75ac8db68f09d3ccbb6b7e32eec2a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=939d9a906ff75ac8db68f09d3ccbb6b7e32eec2a
Author: Ken Thomases <ken at codeweavers.com>
Date: Thu May 16 16:48:39 2013 -0500
winemac: Improve positioning of input method candidate window.
---
dlls/winemac.drv/cocoa_window.m | 28 +++++++++-
dlls/winemac.drv/event.c | 4 +
dlls/winemac.drv/ime.c | 123 +++++++++++++++++++++++++++++++++++++++
dlls/winemac.drv/macdrv.h | 1 +
dlls/winemac.drv/macdrv_cocoa.h | 6 ++
5 files changed, 161 insertions(+), 1 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index 8ebda3b..daa1e66 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -370,6 +370,8 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
[[window queue] postEvent:event];
macdrv_release_event(event);
+
+ [[self inputContext] invalidateCharacterCoordinates];
}
}
@@ -414,10 +416,32 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
- (NSRect) firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
{
+ macdrv_query* query;
+ WineWindow* window = (WineWindow*)[self window];
+ NSRect ret;
+
aRange = NSIntersectionRange(aRange, NSMakeRange(0, [markedText length]));
+
+ query = macdrv_create_query();
+ query->type = QUERY_IME_CHAR_RECT;
+ query->window = (macdrv_window)[window retain];
+ query->ime_char_rect.data = [window imeData];
+ query->ime_char_rect.range = CFRangeMake(aRange.location, aRange.length);
+
+ if ([window.queue query:query timeout:1])
+ {
+ aRange = NSMakeRange(query->ime_char_rect.range.location, query->ime_char_rect.range.length);
+ ret = NSRectFromCGRect(query->ime_char_rect.rect);
+ [[WineApplicationController sharedController] flipRect:&ret];
+ }
+ else
+ ret = NSMakeRect(100, 100, aRange.length ? 1 : 0, 12);
+
+ macdrv_release_query(query);
+
if (actualRange)
*actualRange = aRange;
- return NSMakeRect(100, 100, aRange.length ? 1 : 0, 12);
+ return ret;
}
- (NSUInteger) characterIndexForPoint:(NSPoint)aPoint
@@ -1211,6 +1235,8 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
event->window_frame_changed.frame = NSRectToCGRect(frame);
[queue postEvent:event];
macdrv_release_event(event);
+
+ [[[self contentView] inputContext] invalidateCharacterCoordinates];
}
- (BOOL)windowShouldClose:(id)sender
diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c
index cb305d6..51f6723 100644
--- a/dlls/winemac.drv/event.c
+++ b/dlls/winemac.drv/event.c
@@ -136,6 +136,10 @@ static void macdrv_query_event(HWND hwnd, const macdrv_event *event)
TRACE("QUERY_DRAG_OPERATION\n");
success = query_drag_operation(query);
break;
+ case QUERY_IME_CHAR_RECT:
+ TRACE("QUERY_IME_CHAR_RECT\n");
+ success = query_ime_char_rect(query);
+ break;
case QUERY_PASTEBOARD_DATA:
TRACE("QUERY_PASTEBOARD_DATA\n");
success = query_pasteboard_data(hwnd, query->pasteboard_data.type);
diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c
index e9f1369..44d5d8b 100644
--- a/dlls/winemac.drv/ime.c
+++ b/dlls/winemac.drv/ime.c
@@ -1509,3 +1509,126 @@ void macdrv_im_set_text(const macdrv_event *event)
if (event->im_set_text.complete)
IME_NotifyComplete(himc);
}
+
+
+/**************************************************************************
+ * query_ime_char_rect
+ */
+BOOL query_ime_char_rect(macdrv_query* query)
+{
+ HWND hwnd = macdrv_get_window_hwnd(query->window);
+ void *himc = query->ime_char_rect.data;
+ CFRange* range = &query->ime_char_rect.range;
+ CGRect* rect = &query->ime_char_rect.rect;
+ IMECHARPOSITION charpos;
+ BOOL ret = FALSE;
+
+ TRACE("win %p/%p himc %p range %ld-%ld\n", hwnd, query->window, himc, range->location,
+ range->length);
+
+ if (!himc) himc = RealIMC(FROM_MACDRV);
+
+ charpos.dwSize = sizeof(charpos);
+ charpos.dwCharPos = range->location;
+ if (ImmRequestMessageW(himc, IMR_QUERYCHARPOSITION, (ULONG_PTR)&charpos))
+ {
+ int i;
+
+ *rect = CGRectMake(charpos.pt.x, charpos.pt.y, 0, charpos.cLineHeight);
+
+ /* iterate over rest of length to extend rect */
+ for (i = 1; i <= range->length; i++)
+ {
+ charpos.dwSize = sizeof(charpos);
+ charpos.dwCharPos = range->location + i;
+ if (!ImmRequestMessageW(himc, IMR_QUERYCHARPOSITION, (ULONG_PTR)&charpos) ||
+ charpos.pt.y != rect->origin.y)
+ {
+ range->length = i;
+ break;
+ }
+
+ rect->size.width = charpos.pt.x - rect->origin.x;
+ }
+
+ ret = TRUE;
+ }
+
+ if (!ret)
+ {
+ LPINPUTCONTEXT ic = ImmLockIMC(himc);
+
+ if (ic)
+ {
+ LPIMEPRIVATE private = ImmLockIMCC(ic->hPrivate);
+ LPBYTE compdata = ImmLockIMCC(ic->hCompStr);
+ LPCOMPOSITIONSTRING compstr = (LPCOMPOSITIONSTRING)compdata;
+ LPWSTR str = (LPWSTR)(compdata + compstr->dwCompStrOffset);
+
+ if (private->hwndDefault && compstr->dwCompStrOffset &&
+ IsWindowVisible(private->hwndDefault))
+ {
+ HDC dc = GetDC(private->hwndDefault);
+ HFONT oldfont = NULL;
+ SIZE size;
+
+ if (private->textfont)
+ oldfont = SelectObject(dc, private->textfont);
+
+ if (range->location > compstr->dwCompStrLen)
+ range->location = compstr->dwCompStrLen;
+ if (range->location + range->length > compstr->dwCompStrLen)
+ range->length = compstr->dwCompStrLen - range->location;
+
+ GetTextExtentPoint32W(dc, str, range->location, &size);
+ charpos.rcDocument.left = size.cx;
+ charpos.rcDocument.top = 0;
+ GetTextExtentPoint32W(dc, str, range->location + range->length, &size);
+ charpos.rcDocument.right = size.cx;
+ charpos.rcDocument.bottom = size.cy;
+
+ if (ic->cfCompForm.dwStyle == CFS_DEFAULT)
+ OffsetRect(&charpos.rcDocument, 10, 10);
+
+ LPtoDP(dc, (POINT*)&charpos.rcDocument, 2);
+ MapWindowPoints(private->hwndDefault, 0, (POINT*)&charpos.rcDocument, 2);
+ *rect = cgrect_from_rect(charpos.rcDocument);
+ ret = TRUE;
+
+ if (oldfont)
+ SelectObject(dc, oldfont);
+ ReleaseDC(private->hwndDefault, dc);
+ }
+
+ ImmUnlockIMCC(ic->hCompStr);
+ ImmUnlockIMCC(ic->hPrivate);
+ }
+
+ ImmUnlockIMC(himc);
+ }
+
+ if (!ret)
+ {
+ HWND focus = GetFocus();
+ if (focus && (focus == hwnd || IsChild(hwnd, focus)) &&
+ GetClientRect(focus, &charpos.rcDocument))
+ {
+ if (!GetCaretPos((POINT*)&charpos.rcDocument))
+ charpos.rcDocument.left = charpos.rcDocument.top = 0;
+
+ charpos.rcDocument.right = charpos.rcDocument.left + 1;
+ MapWindowPoints(focus, 0, (POINT*)&charpos.rcDocument, 2);
+
+ *rect = cgrect_from_rect(charpos.rcDocument);
+ ret = TRUE;
+ }
+ }
+
+ if (ret && range->length && !rect->size.width)
+ rect->size.width = 1;
+
+ TRACE(" -> %s range %ld-%ld rect %s\n", ret ? "TRUE" : "FALSE", range->location,
+ range->length, wine_dbgstr_cgrect(*rect));
+
+ return ret;
+}
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index fed1d47..1010ded 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -204,5 +204,6 @@ extern BOOL macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const B
extern void macdrv_im_set_cursor_pos(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void macdrv_im_set_text(const macdrv_event *event) DECLSPEC_HIDDEN;
+extern BOOL query_ime_char_rect(macdrv_query* query) DECLSPEC_HIDDEN;
#endif /* __WINE_MACDRV_H */
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 84dfd87..905738f 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -259,6 +259,7 @@ enum {
QUERY_DRAG_DROP,
QUERY_DRAG_EXITED,
QUERY_DRAG_OPERATION,
+ QUERY_IME_CHAR_RECT,
QUERY_PASTEBOARD_DATA,
NUM_QUERY_TYPES
};
@@ -284,6 +285,11 @@ typedef struct macdrv_query {
CFTypeRef pasteboard;
} drag_operation;
struct {
+ void *data;
+ CFRange range;
+ CGRect rect;
+ } ime_char_rect;
+ struct {
CFStringRef type;
} pasteboard_data;
};
More information about the wine-cvs
mailing list