mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-16 23:25:03 +00:00
Fix for IME status window problems: 30879,30097,29836. r=erik@netscape.com.
This commit is contained in:
parent
98ee9417b4
commit
5c0f02ca73
@ -344,11 +344,16 @@ nsIMEPreedit::IMSetTextRange(const PRInt32 aLen,
|
||||
|
||||
extern "C" {
|
||||
extern void
|
||||
_XRegisterFilterByType(Display *display, Window window,
|
||||
_XRegisterFilterByType(Display *display, Window window,
|
||||
int start_type, int end_type,
|
||||
Bool (*filter)(Display*, Window,
|
||||
XEvent*, XPointer),
|
||||
XPointer client_data);
|
||||
extern void
|
||||
_XUnregisterFilter(Display *display, Window window,
|
||||
Bool (*filter)(Display*, Window,
|
||||
XEvent*, XPointer),
|
||||
XPointer client_data);
|
||||
extern int _XDefaultError(Display*, XErrorEvent*);
|
||||
}
|
||||
|
||||
@ -442,27 +447,6 @@ validateCoordinates(Display * display, Window w,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nsIMEStatus::move() {
|
||||
Display *display = GDK_DISPLAY();
|
||||
gint wx, wy, wwidth, wheight;
|
||||
wx=((GdkWindowPrivate*)mParent)->x;
|
||||
wy=((GdkWindowPrivate*)mParent)->y;
|
||||
wwidth=((GdkWindowPrivate*)mParent)->width;
|
||||
wheight=((GdkWindowPrivate*)mParent)->height;
|
||||
|
||||
wy += wheight;
|
||||
validateCoordinates(display,mIMStatusWindow,
|
||||
&wx, &wy);
|
||||
|
||||
XWindowChanges changes;
|
||||
int mask = CWX|CWY;
|
||||
changes.x = wx;
|
||||
changes.y = wy;
|
||||
|
||||
XConfigureWindow(display, mIMStatusWindow,
|
||||
mask, &changes);
|
||||
}
|
||||
|
||||
void
|
||||
nsIMEStatus::hide() {
|
||||
@ -478,19 +462,60 @@ nsIMEStatus::hide() {
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nsIMEStatus::UnregisterClientFilter(Window aWindow) {
|
||||
Display *display = GDK_DISPLAY();
|
||||
_XUnregisterFilter(display, aWindow,
|
||||
client_filter, (XPointer)this);
|
||||
}
|
||||
|
||||
void
|
||||
nsIMEStatus::RegisterClientFilter(Window aWindow) {
|
||||
Display *display = GDK_DISPLAY();
|
||||
_XRegisterFilterByType(display, aWindow,
|
||||
ConfigureNotify, ConfigureNotify,
|
||||
client_filter,
|
||||
(XPointer)this);
|
||||
_XRegisterFilterByType(display, aWindow,
|
||||
DestroyNotify, DestroyNotify,
|
||||
client_filter,
|
||||
(XPointer)this);
|
||||
}
|
||||
|
||||
void
|
||||
nsIMEStatus::setParentWindow(GdkWindow *aWindow) {
|
||||
Display *display = GDK_DISPLAY();
|
||||
GdkWindow *newParent = gdk_window_get_toplevel(aWindow);
|
||||
|
||||
if (newParent != mParent) {
|
||||
mParent = newParent;
|
||||
setText("");
|
||||
hide();
|
||||
if (mParent) {
|
||||
UnregisterClientFilter(GDK_WINDOW_XWINDOW(mParent));
|
||||
}
|
||||
mParent = newParent;
|
||||
if (mIMStatusWindow) {
|
||||
XSetTransientForHint(display, mIMStatusWindow,
|
||||
GDK_WINDOW_XWINDOW(mParent));
|
||||
RegisterClientFilter(GDK_WINDOW_XWINDOW(mParent));
|
||||
}
|
||||
if (mText) show();
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
nsIMEStatus::client_filter(Display *aDisplay, Window aWindow,
|
||||
XEvent *aEvent, XPointer aClientData) {
|
||||
nsIMEStatus *thiswindow = (nsIMEStatus*)aClientData;
|
||||
if (thiswindow && NULL != aEvent) {
|
||||
if (ConfigureNotify == aEvent->type) {
|
||||
thiswindow->show();
|
||||
} else if (DestroyNotify == aEvent->type) {
|
||||
thiswindow->UnregisterClientFilter(aWindow);
|
||||
thiswindow->hide();
|
||||
}
|
||||
}
|
||||
if (mText) show();
|
||||
return False;
|
||||
}
|
||||
|
||||
Bool
|
||||
@ -614,18 +639,71 @@ nsIMEStatus::resize(const char *aString) {
|
||||
// public
|
||||
void
|
||||
nsIMEStatus::show() {
|
||||
if (!mText || !nsCRT::strlen(mText)) {
|
||||
// don't map if text is ""
|
||||
return;
|
||||
}
|
||||
|
||||
Display *display = GDK_DISPLAY();
|
||||
|
||||
if (!mIMStatusWindow) {
|
||||
CreateNative();
|
||||
}
|
||||
|
||||
XWindowAttributes win_att;
|
||||
int wx, wy;
|
||||
Window w_none;
|
||||
Window parent = GDK_WINDOW_XWINDOW(mParent);
|
||||
|
||||
// parent window is destroyed
|
||||
if (!parent || ((GdkWindowPrivate*)mParent)->destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// parent window exists but isn't mapped yet
|
||||
if (XGetWindowAttributes(display, parent,
|
||||
&win_att) > 0) {
|
||||
if (win_att.map_state == IsUnmapped) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (XGetWindowAttributes(display, parent, &win_att) > 0) {
|
||||
XTranslateCoordinates(display, parent,
|
||||
win_att.root,
|
||||
-(win_att.border_width),
|
||||
-(win_att.border_width),
|
||||
&wx, &wy, &w_none);
|
||||
wy += win_att.height;
|
||||
|
||||
// adjust position
|
||||
validateCoordinates(display,mIMStatusWindow,
|
||||
&wx, &wy);
|
||||
|
||||
// set position
|
||||
// Linux window manager doesn't work properly
|
||||
// when only XConfigureWindow() is called
|
||||
XSizeHints xsh;
|
||||
(void) memset(&xsh, 0, sizeof(xsh));
|
||||
xsh.flags |= USPosition;
|
||||
xsh.x = wx;
|
||||
xsh.y = wy;
|
||||
XSetWMNormalHints(display, mIMStatusWindow, &xsh);
|
||||
|
||||
XWindowChanges changes;
|
||||
int mask = CWX|CWY;
|
||||
changes.x = wx;
|
||||
changes.y = wy;
|
||||
XConfigureWindow(display, mIMStatusWindow,
|
||||
mask, &changes);
|
||||
}
|
||||
|
||||
if (XGetWindowAttributes(display, mIMStatusWindow,
|
||||
&win_att) > 0) {
|
||||
if (win_att.map_state == IsUnmapped) {
|
||||
XMapWindow(display, mIMStatusWindow);
|
||||
}
|
||||
}
|
||||
move();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -779,6 +857,15 @@ int
|
||||
nsIMEGtkIC::status_start_cbproc(XIC xic, XPointer client_data,
|
||||
XPointer call_data_p)
|
||||
{
|
||||
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
|
||||
if (!thisXIC) return 0;
|
||||
nsWidget *widget = thisXIC->mFocusWidget;
|
||||
if (!widget) return 0;
|
||||
if (!gStatus) return 0;
|
||||
|
||||
// focus_window is changed
|
||||
gStatus->setText("");
|
||||
gStatus->hide();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -799,10 +886,10 @@ nsIMEGtkIC::status_draw_cbproc(XIC xic, XPointer client_data,
|
||||
if (call_data->type == XIMTextType) {
|
||||
XIMText *text = (XIMText *) call_data->data.text;
|
||||
if (!text || !text->length) {
|
||||
//gStatus->setText("");
|
||||
// turn conversion off
|
||||
gStatus->setText("");
|
||||
gStatus->hide();
|
||||
} else {
|
||||
gStatus->show();
|
||||
char *statusStr = 0;
|
||||
if (text->encoding_is_wchar) {
|
||||
if (text->string.wide_char) {
|
||||
@ -816,7 +903,9 @@ nsIMEGtkIC::status_draw_cbproc(XIC xic, XPointer client_data,
|
||||
} else {
|
||||
statusStr = text->string.multi_byte;
|
||||
}
|
||||
// turn conversion on
|
||||
gStatus->setText(statusStr);
|
||||
gStatus->show();
|
||||
if (statusStr && text->encoding_is_wchar) {
|
||||
delete [] statusStr;
|
||||
}
|
||||
@ -863,6 +952,7 @@ nsIMEGtkIC::SetFocusWidget(nsWidget * aFocusWidget)
|
||||
mFocusWidget = aFocusWidget;
|
||||
GdkWindow *gdkWindow = (GdkWindow*)aFocusWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
if (!gdkWindow) return;
|
||||
|
||||
gdk_im_begin((GdkIC *) mIC, gdkWindow);
|
||||
|
||||
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
|
||||
@ -870,11 +960,11 @@ nsIMEGtkIC::SetFocusWidget(nsWidget * aFocusWidget)
|
||||
(int)((GdkWindowPrivate*)gdkWindow)->width,
|
||||
(int)((GdkWindowPrivate*)gdkWindow)->height);
|
||||
}
|
||||
|
||||
if (gInputStyle & GDK_IM_STATUS_CALLBACKS) {
|
||||
if (!gStatus) {
|
||||
gStatus = new nsIMEStatus();
|
||||
if (gStatus) {
|
||||
gStatus->setParentWindow(gdkWindow);
|
||||
}
|
||||
gStatus->setParentWindow(gdkWindow);
|
||||
}
|
||||
}
|
||||
|
||||
@ -902,7 +992,7 @@ nsIMEGtkIC *nsIMEGtkIC::GetXIC(nsWidget * aFocusWidget,
|
||||
|
||||
nsIMEGtkIC::~nsIMEGtkIC()
|
||||
{
|
||||
/* XSetTransientForHint does not work for popup-shell, workaroun */
|
||||
/* XSetTransientForHint does not work for popup-shell, workaround */
|
||||
if (gStatus) {
|
||||
gStatus->hide();
|
||||
}
|
||||
@ -1002,6 +1092,7 @@ XIMErrorHandler(Display *dpy, XErrorEvent *event) {
|
||||
}
|
||||
}
|
||||
_XDefaultError(dpy, event);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1390,6 +1481,14 @@ nsIMEGtkIC::nsIMEGtkIC(nsWidget *aFocusWidget, GdkFont *aFontSet,
|
||||
XNStatusAttributes, status_attr,
|
||||
0);
|
||||
XFree(status_attr);
|
||||
|
||||
if (gInputStyle & GDK_IM_STATUS_CALLBACKS) {
|
||||
if (!gStatus) {
|
||||
gStatus = new nsIMEStatus();
|
||||
}
|
||||
gStatus->setText("");
|
||||
gStatus->setParentWindow(gdkWindow);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -78,10 +78,11 @@ class nsIMEStatus {
|
||||
int mHeight;
|
||||
GC mGC;
|
||||
char *mText;
|
||||
void move();
|
||||
void resize(const char *);
|
||||
void remove_decoration();
|
||||
void getAtoms();
|
||||
static Bool client_filter(Display *d, Window w, XEvent *ev,
|
||||
XPointer client_data);
|
||||
static Bool repaint_filter(Display *d, Window w, XEvent *ev,
|
||||
XPointer client_data);
|
||||
static Bool clientmessage_filter(Display *d, Window w, XEvent *ev,
|
||||
@ -93,6 +94,8 @@ class nsIMEStatus {
|
||||
nsIMEStatus(GdkFont*);
|
||||
void SetFont(GdkFont*);
|
||||
~nsIMEStatus();
|
||||
void UnregisterClientFilter(Window);
|
||||
void RegisterClientFilter(Window);
|
||||
void setText(const char*);
|
||||
void setParentWindow(GdkWindow*);
|
||||
void show();
|
||||
|
Loading…
x
Reference in New Issue
Block a user