winemac: Improve positioning of input method candidate window.

This commit is contained in:
Ken Thomases 2013-05-16 16:48:39 -05:00 committed by Alexandre Julliard
parent 450617ecfc
commit 939d9a906f
5 changed files with 161 additions and 1 deletions

View File

@ -370,6 +370,8 @@ - (void) setMarkedText:(id)string selectedRange:(NSRange)selectedRange replaceme
[[window queue] postEvent:event];
macdrv_release_event(event);
[[self inputContext] invalidateCharacterCoordinates];
}
}
@ -414,10 +416,32 @@ - (NSArray*) validAttributesForMarkedText
- (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 @@ - (void)windowDidResize:(NSNotification *)notification
event->window_frame_changed.frame = NSRectToCGRect(frame);
[queue postEvent:event];
macdrv_release_event(event);
[[[self contentView] inputContext] invalidateCharacterCoordinates];
}
- (BOOL)windowShouldClose:(id)sender

View File

@ -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);

View File

@ -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;
}

View File

@ -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 */

View File

@ -259,6 +259,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
QUERY_DRAG_DROP,
QUERY_DRAG_EXITED,
QUERY_DRAG_OPERATION,
QUERY_IME_CHAR_RECT,
QUERY_PASTEBOARD_DATA,
NUM_QUERY_TYPES
};
@ -283,6 +284,11 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
uint32_t accepted_op;
CFTypeRef pasteboard;
} drag_operation;
struct {
void *data;
CFRange range;
CGRect rect;
} ime_char_rect;
struct {
CFStringRef type;
} pasteboard_data;