summaryrefslogtreecommitdiffstats
path: root/tqtinterface/qt4/src/kernel/tqapplication_x11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tqtinterface/qt4/src/kernel/tqapplication_x11.cpp')
-rw-r--r--tqtinterface/qt4/src/kernel/tqapplication_x11.cpp754
1 files changed, 482 insertions, 272 deletions
diff --git a/tqtinterface/qt4/src/kernel/tqapplication_x11.cpp b/tqtinterface/qt4/src/kernel/tqapplication_x11.cpp
index 48616bf..e7cf92f 100644
--- a/tqtinterface/qt4/src/kernel/tqapplication_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqapplication_x11.cpp
@@ -92,7 +92,9 @@
#include "tqfileinfo.h"
// Input method stuff - UNFINISHED
-#include "tqinputcontext_p.h"
+#ifndef TQT_NO_IM
+#include "tqinputcontext.h"
+#endif // TQT_NO_IM
#include "tqinternal_p.h" // shared double buffer cleanup
#if defined(TQT_THREAD_SUPPORT)
@@ -114,6 +116,7 @@ extern "C" Bool XftInitFtLibrary(void);
#include <string.h>
#include <ctype.h>
#include <locale.h>
+#include <cstdlib>
//#define X_NOT_BROKEN
#ifdef X_NOT_BROKEN
@@ -271,10 +274,16 @@ Atom qt_net_wm_window_type_menu = 0;
Atom qt_net_wm_window_type_utility = 0;
Atom qt_net_wm_window_type_splash = 0;
Atom qt_net_wm_window_type_override = 0; // KDE extension
+Atom qt_net_wm_window_type_dropdown_menu = 0;
+Atom qt_net_wm_window_type_popup_menu = 0;
+Atom qt_net_wm_window_type_tooltip = 0;
+Atom qt_net_wm_window_type_combo = 0;
+Atom qt_net_wm_window_type_dnd = 0;
Atom qt_net_wm_frame_strut = 0; // KDE extension
Atom qt_net_wm_state_stays_on_top = 0; // KDE extension
Atom qt_net_wm_pid = 0;
Atom qt_net_wm_user_time = 0;
+Atom qt_net_wm_full_placement = 0; // KDE extension
// Enlightenment support
Atom qt_enlightenment_desktop = 0;
@@ -284,6 +293,11 @@ Atom *qt_net_supported_list = 0;
Window *qt_net_virtual_root_list = 0;
+// X11 SYNC support
+#ifndef TQT_NO_XSYNC
+Atom qt_net_wm_sync_request_counter = 0;
+Atom qt_net_wm_sync_request = 0;
+#endif
// client leader window
Window qt_x11_wm_client_leader = 0;
@@ -308,6 +322,13 @@ static int xrandr_eventbase;
// Display
TQ_EXPORT bool qt_use_xrender = FALSE;
+#ifndef TQT_NO_XSYNC
+// True if SYNC extension exists on the connected display
+bool qt_use_xsync = FALSE;
+static int xsync_eventbase;
+static int xsync_errorbase;
+#endif
+
// modifier masks for alt/meta - detected when the application starts
static long qt_alt_mask = 0;
static long qt_meta_mask = 0;
@@ -1709,17 +1730,28 @@ void qt_init_internal( int *argcptr, char **argv,
qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_UTILITY", &qt_net_wm_window_type_utility );
qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_SPLASH", &qt_net_wm_window_type_splash );
qt_x11_intern_atom( "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", &qt_net_wm_window_type_override );
+ qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", &qt_net_wm_window_type_dropdown_menu );
+ qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_POPUP_MENU", &qt_net_wm_window_type_popup_menu );
+ qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_TOOLTIP", &qt_net_wm_window_type_tooltip );
+ qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_COMBO", &qt_net_wm_window_type_combo );
+ qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_DND", &qt_net_wm_window_type_dnd );
qt_x11_intern_atom( "_KDE_NET_WM_FRAME_STRUT", &qt_net_wm_frame_strut );
qt_x11_intern_atom( "_NET_WM_STATE_STAYS_ON_TOP",
&qt_net_wm_state_stays_on_top );
qt_x11_intern_atom( "_NET_WM_PID", &qt_net_wm_pid );
qt_x11_intern_atom( "_NET_WM_USER_TIME", &qt_net_wm_user_time );
+ qt_x11_intern_atom( "_NET_WM_FULL_PLACEMENT", &qt_net_wm_full_placement );
qt_x11_intern_atom( "ENLIGHTENMENT_DESKTOP", &qt_enlightenment_desktop );
qt_x11_intern_atom( "_NET_WM_NAME", &qt_net_wm_name );
qt_x11_intern_atom( "_NET_WM_ICON_NAME", &qt_net_wm_icon_name );
qt_x11_intern_atom( "UTF8_STRING", &qt_utf8_string );
qt_x11_intern_atom( "_SGI_DESKS_MANAGER", &qt_sgi_desks_manager );
+#ifndef TQT_NO_XSYNC
+ qt_x11_intern_atom( "_NET_WM_SYNC_REQUEST_COUNTER", &qt_net_wm_sync_request_counter );
+ qt_x11_intern_atom( "_NET_WM_SYNC_REQUEST", &qt_net_wm_sync_request );
+#endif
+
qt_xdnd_setup();
qt_x11_motifdnd_init();
@@ -1756,6 +1788,15 @@ void qt_init_internal( int *argcptr, char **argv,
}
#endif // TQT_NO_XRENDER
+#ifndef TQT_NO_XSYNC
+ // Try to initialize SYNC extension on the connected display
+ int xsync_major, xsync_minor;
+ if ( XSyncQueryExtension( appDpy, &xsync_eventbase, &xsync_errorbase ) &&
+ XSyncInitialize( appDpy, &xsync_major, &xsync_minor ) ) {
+ qt_use_xsync = TRUE;
+ }
+#endif
+
#ifndef TQT_NO_XKB
// If XKB is detected, set the GrabsUseXKBState option so input method
// compositions continue to work (ie. deadkeys)
@@ -2731,10 +2772,9 @@ static const char *appBTNCol = 0; // application btn color
static const char *mwGeometry = 0; // main widget tqgeometry
static const char *mwTitle = 0; // main widget title
//Ming-Che 10/10
-static char *ximServer = 0; // XIM Server will connect to
+char *qt_ximServer = 0; // XIM Server will connect to
static bool mwIconic = FALSE; // main widget iconified
//Ming-Che 10/10
-static bool noxim = FALSE; // connect to xim or not
static Display *appDpy = 0; // X11 application display
static char *appDpyName = 0; // X11 display name
static bool appForeignDpy = FALSE; // we didn't create display
@@ -2933,14 +2973,14 @@ static bool qt_x11EventFilter( XEvent* ev )
#if !defined(TQT_NO_XIM)
-XIM qt_xim = 0;
+//XIM qt_xim = 0;
XIMStyle qt_xim_style = 0;
+XIMStyle qt_xim_preferred_style = 0;
static XIMStyle xim_default_style = XIMPreeditCallbacks | XIMStatusNothing;
-static XIMStyle xim_preferred_style = 0;
#endif
-static int composingKeycode=0;
-static TQTextCodec * input_mapper = 0;
+int qt_ximComposingKeycode=0;
+TQTextCodec * qt_input_mapper = 0;
extern bool qt_check_clipboard_sentinel(); //def in qclipboard_x11.cpp
extern bool qt_check_selection_sentinel(); //def in qclipboard_x11.cpp
@@ -3051,8 +3091,7 @@ public:
void setWFlags( WFlags f ) { TQWidget::setWFlags(f); }
void clearWFlags( WFlags f ) { TQWidget::clearWFlags(f); }
bool translateMouseEvent( const XEvent * );
- bool translateKeyEventInternal( const XEvent *, int& count, TQString& text, int& state, char& ascii, int &code,
- TQEvent::Type &type, bool willRepeat=FALSE );
+ bool translateKeyEventInternal( const XEvent *, int& count, TQString& text, int& state, char& ascii, int &code, TQEvent::Type &type, bool willRepeat=FALSE, bool statefulTranslation=TRUE );
bool translateKeyEvent( const XEvent *, bool grab );
bool translatePaintEvent( const XEvent * );
bool translateConfigEvent( const XEvent * );
@@ -3069,114 +3108,120 @@ public:
// ************************************************************************
-// X Input Method support
+// Input Method support
// ************************************************************************
-#if !defined(TQT_NO_XIM)
+/*!
+ An identifier name of the default input method.
+*/
+TQString TQApplication::defaultIM = "imsw-multi";
-#if defined(TQ_C_CALLBACKS)
-extern "C" {
-#endif // TQ_C_CALLBACKS
-#ifdef USE_X11R6_XIM
- static void xim_create_callback(XIM /*im*/,
- XPointer /*client_data*/,
- XPointer /*call_data*/)
- {
- // qDebug("xim_create_callback");
- TQApplication::create_xim();
- }
+/*!
+ This function handles the query about location of the widget
+ holding the TQInputContext instance for widget \a w.
- static void xim_destroy_callback(XIM /*im*/,
- XPointer /*client_data*/,
- XPointer /*call_data*/)
- {
- // qDebug("xim_destroy_callback");
- TQApplication::close_xim();
- XRegisterIMInstantiateCallback(appDpy, 0, 0, 0,
- (XIMProc) xim_create_callback, 0);
- }
+ The input context is used for text input to widget \a w. By
+ default, it returns the top-level widget of \a w.
-#endif // USE_X11R6_XIM
+ If you want to change the mapping of widget \w to TQInputContext
+ instance, reimplement both this function and
+ TQApplication::icHolderWidgets(). For example, suppose a tabbed web
+ browser. The browser should allocate a input context per tab
+ widget because users may switch the tabs and input a new text
+ during previous input contexts live.
-#if defined(TQ_C_CALLBACKS)
+ See also 'Sharing input context between text widgets' and 'Preedit
+ preservation' section of the class description of TQInputContext.
+
+ \sa TQInputContext, icHolderWidgets()
+*/
+TQWidget *TQApplication::locateICHolderWidget( TQWidget *w )
+{
+ return w->tqtopLevelWidget();
}
-#endif // TQ_C_CALLBACKS
-#endif // TQT_NO_XIM
+/*!
+ This function returns all widgets holding TQInputContext.
-/*! \internal
- Creates the application input method.
- */
-void TQApplication::create_xim()
+ By default, This function returns top-level widgets. So if you
+ want to change the mapping of a widget to TQInputContext instance,
+ you must override this function and locateICHolderWidget().
+
+ \sa locateICHolderWidget()
+*/
+TQWidgetList *TQApplication::icHolderWidgets()
{
-#ifndef TQT_NO_XIM
- qt_xim = XOpenIM( appDpy, 0, 0, 0 );
- if ( qt_xim ) {
+ return TQApplication::tqtopLevelWidgets();
+}
-#ifdef USE_X11R6_XIM
- XIMCallback destroy;
- destroy.callback = (XIMProc) xim_destroy_callback;
- destroy.client_data = 0;
- if ( XSetIMValues( qt_xim, XNDestroyCallback, &destroy, (char *) 0 ) != 0 )
- qWarning( "Xlib dosn't support destroy callback");
-#endif // USE_X11R6_XIM
- XIMStyles *styles = 0;
- XGetIMValues(qt_xim, XNQueryInputStyle, &styles, (char *) 0, (char *) 0);
- if ( styles ) {
- int i;
- for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) {
- if ( styles->supported_styles[i] == xim_preferred_style ) {
- qt_xim_style = xim_preferred_style;
- break;
- }
- }
- // if the preferred input style couldn't be found, look for
- // Nothing
- for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) {
- if ( styles->supported_styles[i] == (XIMPreeditNothing |
- XIMStatusNothing) ) {
- qt_xim_style = XIMPreeditNothing | XIMStatusNothing;
- break;
- }
- }
- // ... and failing that, None.
- for ( i = 0; !qt_xim_style && i < styles->count_styles; i++ ) {
- if ( styles->supported_styles[i] == (XIMPreeditNone |
- XIMStatusNone) ) {
- qt_xim_style = XIMPreeditNone | XIMStatusNone;
- break;
- }
- }
+/*!
+ This function replaces all TQInputContext instances in the
+ application. The function's argument is the identifier name of
+ the newly selected input method.
+*/
+void TQApplication::changeAllInputContext( const TQString &identifierName )
+{
+ TQWidgetList *list = tqApp->icHolderWidgets();
+ TQWidgetListIt it(*list);
+ while(it.current()) {
+ it.current()->changeInputContext( identifierName );
+ ++it;
+ }
+ delete list;
- // qDebug("TQApplication: using im style %lx", qt_xim_style);
- XFree( (char *)styles );
- }
+ // defaultIM = identifierName ; // Change of defaultIM -- default input method -- may be enabled.
+}
- if ( qt_xim_style ) {
-#ifdef USE_X11R6_XIM
- XUnregisterIMInstantiateCallback(appDpy, 0, 0, 0,
- (XIMProc) xim_create_callback, 0);
-#endif // USE_X11R6_XIM
+/*!
+ \internal
+ This is an internal function, you should never call this.
- TQWidgetList *list= tqApp->tqtopLevelWidgets();
- TQWidgetListIt it(*list);
- TQWidget * w;
- while( (w=it.current()) != 0 ) {
- ++it;
- w->createTLSysExtra();
- }
- delete list;
- } else {
- // Give up
- qWarning( "No supported input style found."
- " See InputMethod documentation.");
- close_xim();
- }
+ \sa TQInputContext::imEventGenerated()
+*/
+void TQApplication::postIMEvent( TQObject *receiver, TQIMEvent *event )
+{
+ if ( event->type() == TQEvent::IMCompose ) {
+ // enable event compression to reduce preedit flicker on fast
+ // typing
+ postEvent( receiver, event );
+ } else {
+ // cancel queued preedit update
+ if ( event->type() == TQEvent::IMEnd )
+ removePostedEvents( receiver, TQEvent::IMCompose );
+
+ // to avoid event receiving order inversion between TQKeyEvent
+ // and TQIMEvent, we must send IMStart and IMEnd via
+ // sendEvent().
+ sendEvent( receiver, event );
+ delete event;
}
+}
+
+
+/*!
+ This function returns the identifier name of the default input
+ method in this Application. The value is identical to the value of
+ TQApplication::defaultIM.
+*/
+TQString TQApplication::defaultInputMethod()
+{
+ return TQApplication::defaultIM;
+}
+
+
+#if !defined(TQT_NO_IM_EXTENSIONS)
+/*! \internal
+ Creates the application input method.
+*/
+void TQApplication::create_im()
+{
+#ifndef TQT_NO_XIM
+ if ( ! qt_xim_preferred_style ) // no configured input style, use the default
+ qt_xim_preferred_style = xim_default_style;
#endif // TQT_NO_XIM
}
@@ -3184,6 +3229,43 @@ void TQApplication::create_xim()
/*! \internal
Closes the application input method.
*/
+void TQApplication::close_im()
+{
+ TQWidgetList *list = tqApp->icHolderWidgets();
+ TQWidgetListIt it(*list);
+ while(it.current()) {
+ it.current()->destroyInputContext();
+ ++it;
+ }
+ delete list;
+}
+
+#else
+
+/*! \internal
+ Creates the application input method.
+*/
+void TQApplication::create_xim()
+{
+#ifndef TQT_NO_XIM
+ if ( ! qt_xim_preferred_style ) // no configured input style, use the default
+ qt_xim_preferred_style = xim_default_style;
+#endif // TQT_NO_XIM
+
+ TQWidgetList *list= tqApp->tqtopLevelWidgets();
+ TQWidgetListIt it(*list);
+ TQWidget * w;
+ while( (w=it.current()) != 0 ) {
+ ++it;
+ w->createTLSysExtra();
+ }
+ delete list;
+}
+
+
+ /*! \internal
+ Closes the application input method.
+ */
void TQApplication::close_xim()
{
#ifndef TQT_NO_XIM
@@ -3191,7 +3273,10 @@ void TQApplication::close_xim()
// XCloseIM( qt_xim );
// We prefer a less serious memory leak
- qt_xim = 0;
+ // if ( qt_xim )
+ // qt_xim = 0;
+
+#endif // TQT_NO_XIM
TQWidgetList *list = tqApp->tqtopLevelWidgets();
TQWidgetListIt it(*list);
while(it.current()) {
@@ -3199,9 +3284,8 @@ void TQApplication::close_xim()
++it;
}
delete list;
-#endif // TQT_NO_XIM
}
-
+#endif
/*****************************************************************************
Default X error handlers
@@ -3572,18 +3656,40 @@ bool TQApplication::x11_apply_settings()
settings.readBoolEntry("/qt/useRtlExtensions", FALSE);
#ifndef TQT_NO_XIM
- if (xim_preferred_style == 0) {
+ if (qt_xim_preferred_style == 0) {
TQString ximInputStyle =
settings.readEntry( "/qt/XIMInputStyle",
TQObject::trUtf8( "On The Spot" ) ).lower();
if ( ximInputStyle == "on the spot" )
- xim_preferred_style = XIMPreeditCallbacks | XIMStatusNothing;
+ qt_xim_preferred_style = XIMPreeditCallbacks | XIMStatusNothing;
else if ( ximInputStyle == "over the spot" )
- xim_preferred_style = XIMPreeditPosition | XIMStatusNothing;
+ qt_xim_preferred_style = XIMPreeditPosition | XIMStatusNothing;
else if ( ximInputStyle == "off the spot" )
- xim_preferred_style = XIMPreeditArea | XIMStatusArea;
+ qt_xim_preferred_style = XIMPreeditArea | XIMStatusArea;
else if ( ximInputStyle == "root" )
- xim_preferred_style = XIMPreeditNothing | XIMStatusNothing;
+ qt_xim_preferred_style = XIMPreeditNothing | XIMStatusNothing;
+ }
+#endif
+
+#ifndef TQT_NO_IM
+ /*
+ The identifier name of an input method is acquired from the
+ configuration file as a default. If a environment variable
+ "TQT_IM_SWITCHER" is not empty it will overwrite the
+ configuration file. The "imsw-multi" becomes the default if the entry
+ is not configured.
+ */
+ if ( getenv( "TQT_IM_SWITCHER" ) )
+ defaultIM = getenv( "TQT_IM_SWITCHER" );
+#ifndef TQT_NO_IM_EXTENSIONS
+ else
+ defaultIM = settings.readEntry( "/qt/DefaultInputMethodSwitcher", "imsw-multi" );
+#endif
+
+ // defaultIM is restricted to be an IM-switcher. An IM-switcher
+ // has a 'imsw-' prefix
+ if ( ! defaultIM.startsWith( "imsw-" ) ) {
+ defaultIM = "imsw-multi";
}
#endif
@@ -3619,19 +3725,19 @@ static void qt_set_input_encoding()
// Always use the locale codec, since we have no examples of non-local
// XIMs, and since we cannot get a sensible answer about the encoding
// from the XIM.
- input_mapper = TQTextCodec::codecForLocale();
+ qt_input_mapper = TQTextCodec::codecForLocale();
} else {
if ( !qstricmp( data, "locale" ) )
- input_mapper = TQTextCodec::codecForLocale();
+ qt_input_mapper = TQTextCodec::codecForLocale();
else
- input_mapper = TQTextCodec::codecForName( data );
+ qt_input_mapper = TQTextCodec::codecForName( data );
// make sure we have an input codec
- if( !input_mapper )
- input_mapper = TQTextCodec::codecForName( "ISO 8859-1" );
+ if( !qt_input_mapper )
+ qt_input_mapper = TQTextCodec::codecForName( "ISO 8859-1" );
}
- if ( input_mapper->mibEnum() == 11 ) // 8859-8
- input_mapper = TQTextCodec::codecForName( "ISO 8859-8-I");
+ if ( qt_input_mapper->mibEnum() == 11 ) // 8859-8
+ qt_input_mapper = TQTextCodec::codecForName( "ISO 8859-8-I");
if( data )
XFree( (char *)data );
}
@@ -4071,6 +4177,8 @@ static Visual *tqfind_truecolor_visual( Display *dpy, int scr, int *depth, int *
#define XK_MISCELLANY
#define XK_LATIN1
+#define XK_KOREAN
+#define XK_XKB_KEYS
#include <X11/keysymdef.h>
// ### This should be static but it isn't because of the friend declaration
@@ -4161,10 +4269,7 @@ void qt_init_internal( int *argcptr, char **argv,
//Ming-Che 10/10
} else if ( arg == "-im" ) {
if ( ++i < argc )
- ximServer = argv[i];
- } else if ( arg == "-noxim" ) {
- noxim=TRUE;
- //
+ qt_ximServer = argv[i];
} else if ( arg == "-iconic" ) {
mwIconic = !mwIconic;
} else if ( arg == "-ncols" ) { // xv and netscape use this name
@@ -4184,17 +4289,17 @@ void qt_init_internal( int *argcptr, char **argv,
if ( ++i < argc ) {
TQCString s = TQCString(argv[i]).lower();
if ( s == "onthespot" )
- xim_preferred_style = XIMPreeditCallbacks |
- XIMStatusNothing;
+ qt_xim_preferred_style = XIMPreeditCallbacks |
+ XIMStatusNothing;
else if ( s == "overthespot" )
- xim_preferred_style = XIMPreeditPosition |
- XIMStatusNothing;
+ qt_xim_preferred_style = XIMPreeditPosition |
+ XIMStatusNothing;
else if ( s == "offthespot" )
- xim_preferred_style = XIMPreeditArea |
- XIMStatusArea;
+ qt_xim_preferred_style = XIMPreeditArea |
+ XIMStatusArea;
else if ( s == "root" )
- xim_preferred_style = XIMPreeditNothing |
- XIMStatusNothing;
+ qt_xim_preferred_style = XIMPreeditNothing |
+ XIMStatusNothing;
}
#endif
} else if ( arg == "-cmap" ) { // xv uses this name
@@ -4642,34 +4747,13 @@ void qt_init_internal( int *argcptr, char **argv,
TQApplication::setFont( f );
}
-#ifndef TQT_NO_XIM
- if ( ! xim_preferred_style ) // no configured input style, use the default
- xim_preferred_style = xim_default_style;
-
- qt_xim = 0;
- TQString ximServerName(ximServer);
- if (ximServer)
- ximServerName.prepend("@im=");
- else
- ximServerName = "";
-
- if ( !XSupportsLocale() )
- qWarning("TQt: Locales not supported on X server");
-
-#ifdef USE_X11R6_XIM
- else if ( XSetLocaleModifiers (ximServerName.ascii()) == 0 )
- qWarning( "TQt: Cannot set locale modifiers: %s",
- ximServerName.ascii());
- else if (! noxim)
- XRegisterIMInstantiateCallback(appDpy, 0, 0, 0,
- (XIMProc) xim_create_callback, 0);
-#else // !USE_X11R6_XIM
- else if ( XSetLocaleModifiers ("") == 0 )
- qWarning("TQt: Cannot set locale modifiers");
- else if (! noxim)
- TQApplication::create_xim();
-#endif // USE_X11R6_XIM
-#endif // TQT_NO_XIM
+#if !defined(TQT_NO_IM)
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ TQApplication::create_im();
+#else
+ TQApplication::create_xim();
+#endif
+#endif
#if defined (TQT_TABLET_SUPPORT)
int ndev,
@@ -4918,9 +5002,12 @@ void qt_cleanup()
XCloseDevice( appDpy, devEraser );
#endif
-#if !defined(TQT_NO_XIM)
- if ( qt_xim )
- TQApplication::close_xim();
+#if !defined(TQT_NO_IM)
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ TQApplication::close_im();
+#else
+ TQApplication::close_xim();
+#endif
#endif
if ( qt_is_gui_used ) {
@@ -5673,6 +5760,10 @@ int TQApplication::x11ClientMessage(TQWidget* w, XEvent* event, bool passive_onl
XSendEvent( event->xclient.display, event->xclient.window,
False, SubstructureNotifyMask|SubstructureRedirectMask, event );
}
+#ifndef TQT_NO_XSYNC
+ } else if (a == qt_net_wm_sync_request ) {
+ widget->handleSyncRequest( event );
+#endif
}
} else if ( event->xclient.message_type == qt_qt_scrolldone ) {
widget->translateScrollDoneEvent(event);
@@ -5779,77 +5870,59 @@ int TQApplication::x11ProcessEvent( XEvent* event )
}
}
- int xkey_keycode = event->xkey.keycode;
- if ( XFilterEvent( event,
- keywidget ? keywidget->tqtopLevelWidget()->winId() : None ) ) {
- if ( keywidget )
- composingKeycode = xkey_keycode; // ### not documented in xlib
+#ifndef TQT_NO_IM
+ // Filtering input events by the input context. It has to be taken
+ // place before any other key event consumers such as eventfilters
+ // and accelerators because some input methods require quite
+ // various key combination and sequences. It often conflicts with
+ // accelerators and so on, so we must give the input context the
+ // filtering opportunity first to ensure all input methods work
+ // properly regardless of application design.
-#ifndef TQT_NO_XIM
- if ( event->type != XKeyPress || ! (qt_xim_style & XIMPreeditCallbacks) )
- return 1;
-
- /*
- * The Solaris htt input method will transform a ClientMessage
- * event into a filtered KeyPress event, in which case our
- * keywidget is still zero.
- */
- if ( ! keywidget ) {
- keywidget = (TQETWidget*)TQWidget::keyboardGrabber();
- if ( keywidget ) {
- grabbed = TRUE;
- } else {
- if ( focus_widget )
- keywidget = (TQETWidget*)focus_widget;
- if ( !keywidget ) {
- if ( inPopupMode() ) // no focus widget, see if we have a popup
- keywidget = (TQETWidget*) activePopupWidget();
- else if ( widget )
- keywidget = (TQETWidget*)widget->tqtopLevelWidget();
- }
- }
- }
-
- /*
- if the composition string has been emptied, we need to send
- an IMEnd event. however, we have no way to tell if the user
- has cancelled input, or if the user has accepted the
- composition.
-
- so, we have to look for the next keypress and see if it is
- the 'commit' key press (keycode == 0). if it is, we deliver
- an IMEnd event with the final text, otherwise we deliver an
- IMEnd with empty text (meaning the user has cancelled the
- input).
- */
- TQInputContext *qic =
- (TQInputContext *) keywidget->tqtopLevelWidget()->topData()->xic;
- extern bool qt_compose_emptied; // qinputcontext_x11.cpp
- if ( qic && qic->composing && qic->tqfocusWidget && qt_compose_emptied ) {
- XEvent event2;
- bool found = FALSE;
- if ( XCheckTypedEvent( TQPaintDevice::x11AppDisplay(),
- XKeyPress, &event2 ) ) {
- if ( event2.xkey.keycode == 0 ) {
- // found a key event with the 'commit' string
- found = TRUE;
- XPutBackEvent( TQPaintDevice::x11AppDisplay(), &event2 );
- }
- }
-
- if ( !found ) {
- // no key event, so the user must have cancelled the composition
- TQIMEvent endevent( TQEvent::IMEnd, TQString::null, -1 );
- TQApplication::sendEvent( qic->tqfocusWidget, &endevent );
+// #ifndef TQT_NO_IM_EXTENSIONS
+ if( keywidget && keywidget->isEnabled() && keywidget->isInputMethodEnabled() ) {
+// #else
+// if( keywidget && keywidget->isEnabled() ) {
+// #endif
+ if( ( event->type==XKeyPress || event->type==XKeyRelease ) &&
+ sm_blockUserInput ) // block user interaction during session management
+ return TRUE;
- qic->tqfocusWidget = 0;
- }
+ // for XIM handling
+ TQInputContext *qic = keywidget->getInputContext();
+ if( qic && qic->x11FilterEvent( keywidget, event ) )
+ return TRUE;
- qt_compose_emptied = FALSE;
+ // filterEvent() accepts TQEvent *event rather than preexpanded key
+ // event attribute values. This is intended to pass other IM-related
+ // events in future. The IM-related events are supposed as
+ // TQWheelEvent, TQTabletEvent and so on. Other non IM-related events
+ // should not be forwarded to input contexts to prevent weird event
+ // handling.
+ if ( ( event->type == XKeyPress || event->type == XKeyRelease ) ) {
+ int code = -1;
+ int count = 0;
+ int state;
+ char ascii = 0;
+ TQEvent::Type type;
+ TQString text;
+
+ keywidget->translateKeyEventInternal( event, count, text,
+ state, ascii, code, type,
+ FALSE, FALSE );
+
+ // both key press/release is required for some complex
+ // input methods. don't eliminate anything.
+ TQKeyEvent keyevent( type, code, ascii, state, text, FALSE, count );
+
+ if( qic && qic->filterEvent( &keyevent ) )
+ return TRUE;
}
-#endif // TQT_NO_XIM
-
- return 1;
+ } else
+#endif // TQT_NO_IM
+ {
+ if ( XFilterEvent( event, None ) )
+ return TRUE;
}
if ( qt_x11EventFilter(event) ) // send through app filter
@@ -5946,7 +6019,8 @@ int TQApplication::x11ProcessEvent( XEvent* event )
#endif
#ifndef TQT_NO_XRANDR
- if (event->type == xrandr_eventbase + RRScreenChangeNotify) {
+ if (event->type == xrandr_eventbase + RRScreenChangeNotify
+ || ( event->type == ConfigureNotify && event->xconfigure.window == TQPaintDevice::x11AppRootWindow())) {
// update Xlib internals with the latest screen configuration
XRRUpdateConfiguration(event);
@@ -6000,34 +6074,8 @@ int TQApplication::x11ProcessEvent( XEvent* event )
case XKeyRelease:
{
if ( keywidget && keywidget->isEnabled() ) { // should always exist
-#ifndef TQT_NO_XIM
- TQInputContext *qic =
- (TQInputContext *) keywidget->tqtopLevelWidget()->topData()->xic;
-
- if ((qt_xim_style & XIMPreeditCallbacks) && event->xkey.keycode == 0 &&
- qic && qic->composing && qic->tqfocusWidget) {
- // input method has sent us a commit string
- TQCString data(513);
- KeySym sym; // unused
- Status status; // unused
- TQString text;
- int count = qic->lookupString( &(event->xkey), data,
- &sym, &status );
- if ( count > 0 )
- text = input_mapper->toUnicode( data, count );
-
- // qDebug( "sending IMEnd with %d chars", text.length() );
- TQIMEvent endevent( TQEvent::IMEnd, text, -1 );
- TQApplication::sendEvent( qic->tqfocusWidget, &endevent );
-
- qic->tqfocusWidget = 0;
- qic->text = TQString::null;
- } else
-#endif // !TQT_NO_XIM
- {
- // qDebug( "sending key event" );
- keywidget->translateKeyEvent( event, grabbed );
- }
+ // qDebug( "sending key event" );
+ keywidget->translateKeyEvent( event, grabbed );
}
break;
}
@@ -6514,7 +6562,7 @@ void TQApplication::closePopup( TQWidget *popup )
// Keyboard event translation
//
-static int translateButtonState( int s )
+int qt_x11_translateButtonState( int s )
{
int bst = 0;
if ( s & Button1Mask )
@@ -6580,7 +6628,7 @@ bool TQETWidget::translateMouseEvent( const XEvent *event )
pos.ry() = lastMotion.y;
globalPos.rx() = lastMotion.x_root;
globalPos.ry() = lastMotion.y_root;
- state = translateButtonState( lastMotion.state );
+ state = qt_x11_translateButtonState( lastMotion.state );
if ( qt_button_down && (state & (LeftButton |
MidButton |
RightButton ) ) == 0 )
@@ -6604,7 +6652,7 @@ bool TQETWidget::translateMouseEvent( const XEvent *event )
pos.ry() = xevent->xcrossing.y;
globalPos.rx() = xevent->xcrossing.x_root;
globalPos.ry() = xevent->xcrossing.y_root;
- state = translateButtonState( xevent->xcrossing.state );
+ state = qt_x11_translateButtonState( xevent->xcrossing.state );
if ( qt_button_down && (state & (LeftButton |
MidButton |
RightButton ) ) == 0 )
@@ -6616,7 +6664,7 @@ bool TQETWidget::translateMouseEvent( const XEvent *event )
pos.ry() = event->xbutton.y;
globalPos.rx() = event->xbutton.x_root;
globalPos.ry() = event->xbutton.y_root;
- state = translateButtonState( event->xbutton.state );
+ state = qt_x11_translateButtonState( event->xbutton.state );
switch ( event->xbutton.button ) {
case Button1: button = LeftButton; break;
case Button2: button = MidButton; break;
@@ -7322,6 +7370,92 @@ static const KeySym KeyTbl[] = { // keyboard mapping table
0x1005FF10, TQt::Key_F11, // hardcoded Sun F36 (labeled F11)
0x1005FF11, TQt::Key_F12, // hardcoded Sun F37 (labeled F12)
+ // International input method support keys
+
+ // International & multi-key character composition
+ XK_Multi_key, TQt::Key_Multi_key,
+ XK_Codeinput, TQt::Key_Codeinput,
+ XK_SingleCandidate, TQt::Key_SingleCandidate,
+ XK_MultipleCandidate, TQt::Key_MultipleCandidate,
+ XK_PreviousCandidate, TQt::Key_PreviousCandidate,
+
+ // Misc Functions
+ XK_Mode_switch, TQt::Key_Mode_switch,
+ //XK_script_switch, TQt::Key_script_switch,
+ XK_script_switch, TQt::Key_Mode_switch,
+
+ // Japanese keyboard support
+ XK_Kanji, TQt::Key_Kanji,
+ XK_Muhenkan, TQt::Key_Muhenkan,
+ //XK_Henkan_Mode, TQt::Key_Henkan_Mode,
+ XK_Henkan_Mode, TQt::Key_Henkan,
+ XK_Henkan, TQt::Key_Henkan,
+ XK_Romaji, TQt::Key_Romaji,
+ XK_Hiragana, TQt::Key_Hiragana,
+ XK_Katakana, TQt::Key_Katakana,
+ XK_Hiragana_Katakana, TQt::Key_Hiragana_Katakana,
+ XK_Zenkaku, TQt::Key_Zenkaku,
+ XK_Hankaku, TQt::Key_Hankaku,
+ XK_Zenkaku_Hankaku, TQt::Key_Zenkaku_Hankaku,
+ XK_Touroku, TQt::Key_Touroku,
+ XK_Massyo, TQt::Key_Massyo,
+ XK_Kana_Lock, TQt::Key_Kana_Lock,
+ XK_Kana_Shift, TQt::Key_Kana_Shift,
+ XK_Eisu_Shift, TQt::Key_Eisu_Shift,
+ XK_Eisu_toggle, TQt::Key_Eisu_toggle,
+ //XK_Kanji_Bangou, TQt::Key_Kanji_Bangou,
+ //XK_Zen_Koho, TQt::Key_Zen_Koho,
+ //XK_Mae_Koho, TQt::Key_Mae_Koho,
+ XK_Kanji_Bangou, TQt::Key_Codeinput,
+ XK_Zen_Koho, TQt::Key_MultipleCandidate,
+ XK_Mae_Koho, TQt::Key_PreviousCandidate,
+
+#ifdef XK_KOREAN
+ // Korean keyboard support
+ XK_Hangul, TQt::Key_Hangul,
+ XK_Hangul_Start, TQt::Key_Hangul_Start,
+ XK_Hangul_End, TQt::Key_Hangul_End,
+ XK_Hangul_Hanja, TQt::Key_Hangul_Hanja,
+ XK_Hangul_Jamo, TQt::Key_Hangul_Jamo,
+ XK_Hangul_Romaja, TQt::Key_Hangul_Romaja,
+ //XK_Hangul_Codeinput, TQt::Key_Hangul_Codeinput,
+ XK_Hangul_Codeinput, TQt::Key_Codeinput,
+ XK_Hangul_Jeonja, TQt::Key_Hangul_Jeonja,
+ XK_Hangul_Banja, TQt::Key_Hangul_Banja,
+ XK_Hangul_PreHanja, TQt::Key_Hangul_PreHanja,
+ XK_Hangul_PostHanja, TQt::Key_Hangul_PostHanja,
+ //XK_Hangul_SingleCandidate, TQt::Key_Hangul_SingleCandidate,
+ //XK_Hangul_MultipleCandidate, TQt::Key_Hangul_MultipleCandidate,
+ //XK_Hangul_PreviousCandidate, TQt::Key_Hangul_PreviousCandidate,
+ XK_Hangul_SingleCandidate, TQt::Key_SingleCandidate,
+ XK_Hangul_MultipleCandidate, TQt::Key_MultipleCandidate,
+ XK_Hangul_PreviousCandidate, TQt::Key_PreviousCandidate,
+ XK_Hangul_Special, TQt::Key_Hangul_Special,
+ //XK_Hangul_switch, TQt::Key_Hangul_switch,
+ XK_Hangul_switch, TQt::Key_Mode_switch,
+#endif // XK_KOREAN
+
+ // dead keys
+ XK_dead_grave, TQt::Key_Dead_Grave,
+ XK_dead_acute, TQt::Key_Dead_Acute,
+ XK_dead_circumflex, TQt::Key_Dead_Circumflex,
+ XK_dead_tilde, TQt::Key_Dead_Tilde,
+ XK_dead_macron, TQt::Key_Dead_Macron,
+ XK_dead_breve, TQt::Key_Dead_Breve,
+ XK_dead_abovedot, TQt::Key_Dead_Abovedot,
+ XK_dead_diaeresis, TQt::Key_Dead_Diaeresis,
+ XK_dead_abovering, TQt::Key_Dead_Abovering,
+ XK_dead_doubleacute, TQt::Key_Dead_Doubleacute,
+ XK_dead_caron, TQt::Key_Dead_Caron,
+ XK_dead_cedilla, TQt::Key_Dead_Cedilla,
+ XK_dead_ogonek, TQt::Key_Dead_Ogonek,
+ XK_dead_iota, TQt::Key_Dead_Iota,
+ XK_dead_voiced_sound, TQt::Key_Dead_Voiced_Sound,
+ XK_dead_semivoiced_sound, TQt::Key_Dead_Semivoiced_Sound,
+ XK_dead_belowdot, TQt::Key_Dead_Belowdot,
+ XK_dead_hook, TQt::Key_Dead_Hook,
+ XK_dead_horn, TQt::Key_Dead_Horn,
+
// Special multimedia keys
// currently only tested with MS internet keyboard
@@ -7539,9 +7673,9 @@ static TQChar keysymToUnicode(unsigned char byte3, unsigned char byte4)
bool TQETWidget::translateKeyEventInternal( const XEvent *event, int& count,
TQString& text,
int& state,
- char& ascii, int& code, TQEvent::Type &type, bool willRepeat )
+ char& ascii, int& code, TQEvent::Type &type, bool willRepeat, bool statefulTranslation )
{
- TQTextCodec *mapper = input_mapper;
+ TQTextCodec *mapper = qt_input_mapper;
// some XmbLookupString implementations don't return buffer overflow correctly,
// so we increase the input buffer to allow for long strings...
// 256 chars * 2 bytes + 1 null-term == 513 bytes
@@ -7562,7 +7696,7 @@ bool TQETWidget::translateKeyEventInternal( const XEvent *event, int& count,
XKeyEvent xkeyevent = event->xkey;
// save the modifier state, we will use the keystate uint later by passing
- // it to translateButtonState
+ // it to qt_x11_translateButtonState
uint keystate = event->xkey.state;
// remove the modifiers where mode_switch exists... HPUX machines seem
// to have alt *AND* mode_switch both in Mod1Mask, which causes
@@ -7588,6 +7722,11 @@ bool TQETWidget::translateKeyEventInternal( const XEvent *event, int& count,
if ( type == TQEvent::KeyPress ) {
bool mb=FALSE;
+ // commit string handling is done by
+ // TQXIMInputContext::x11FilterEvent() and are passed to
+ // widgets via TQIMEvent regardless of XIM style, so the
+ // following code is commented out.
+#if 0
if ( qt_xim ) {
TQTLWExtra* xd = tlw->topData();
TQInputContext *qic = (TQInputContext *) xd->xic;
@@ -7596,13 +7735,14 @@ bool TQETWidget::translateKeyEventInternal( const XEvent *event, int& count,
count = qic->lookupString(&xkeyevent, chars, &key, &status);
}
}
+#endif
if ( !mb ) {
count = XLookupString( &xkeyevent,
chars.data(), chars.size(), &key, 0 );
}
if ( count && !keycode ) {
- keycode = composingKeycode;
- composingKeycode = 0;
+ keycode = qt_ximComposingKeycode;
+ qt_ximComposingKeycode = 0;
}
if ( key )
keyDict->tqreplace( keycode, (void*)key );
@@ -7666,28 +7806,32 @@ bool TQETWidget::translateKeyEventInternal( const XEvent *event, int& count,
} else {
key = (int)(long)keyDict->tqfind( keycode );
if ( key )
- if( !willRepeat ) // Take out key of dictionary only if this call.
+ if( !willRepeat && statefulTranslation ) // Take out key of dictionary only if this call.
keyDict->take( keycode );
long s = (long)textDict->tqfind( keycode );
if ( s ) {
- textDict->take( keycode );
+ if( statefulTranslation )
+ textDict->take( keycode );
ascii = (char)(s-256);
}
}
#endif // !TQT_NO_XIM
- state = translateButtonState( keystate );
+ state = qt_x11_translateButtonState( keystate );
static int directionKeyEvent = 0;
- if ( qt_use_rtl_extensions && type == TQEvent::KeyRelease ) {
+ static unsigned int lastWinId = 0;
+ if ( qt_use_rtl_extensions && type == TQEvent::KeyRelease && statefulTranslation ) {
if (directionKeyEvent == Key_Direction_R || directionKeyEvent == Key_Direction_L ) {
type = TQEvent::KeyPress;
code = directionKeyEvent;
chars[0] = 0;
directionKeyEvent = 0;
+ lastWinId = 0;
return TRUE;
} else {
directionKeyEvent = 0;
+ lastWinId = 0;
}
}
@@ -7697,10 +7841,14 @@ bool TQETWidget::translateKeyEventInternal( const XEvent *event, int& count,
// (to figure out whether the Ctrl modifier is held while Shift is pressed,
// or Shift is held while Ctrl is pressed) since the 'state' doesn't tell
// us whether the modifier held is Left or Right.
- if (qt_use_rtl_extensions && type == TQEvent::KeyPress)
+ if ( qt_use_rtl_extensions && type == TQEvent::KeyPress && statefulTranslation )
if (key == XK_Control_L || key == XK_Control_R || key == XK_Shift_L || key == XK_Shift_R) {
- if (!directionKeyEvent)
+ if (!directionKeyEvent) {
directionKeyEvent = key;
+ // This code exists in order to check that
+ // the event is occurred in the same widget.
+ lastWinId = winId();
+ }
} else {
// this can no longer be a direction-changing accel.
// if any other key was pressed.
@@ -7714,7 +7862,7 @@ bool TQETWidget::translateKeyEventInternal( const XEvent *event, int& count,
// TQt keycodes between 128 and 255, but should rather use the
// TQKeyEvent::text().
//
- if ( key < 128 || (key < 256 && (!input_mapper || input_mapper->mibEnum()==4)) ) {
+ if ( key < 128 || (key < 256 && (!qt_input_mapper || qt_input_mapper->mibEnum()==4)) ) {
code = isprint((int)key) ? toupper((int)key) : 0; // upper-case key, if known
} else if ( key >= XK_F1 && key <= XK_F35 ) {
code = Key_F1 + ((int)key - XK_F1); // function keys
@@ -7765,8 +7913,8 @@ bool TQETWidget::translateKeyEventInternal( const XEvent *event, int& count,
chars[0] = 0;
}
- if ( qt_use_rtl_extensions && type == TQEvent::KeyPress ) {
- if ( directionKeyEvent ) {
+ if ( qt_use_rtl_extensions && type == TQEvent::KeyPress && statefulTranslation ) {
+ if ( directionKeyEvent && lastWinId == winId() ) {
if ( key == XK_Shift_L && directionKeyEvent == XK_Control_L ||
key == XK_Control_L && directionKeyEvent == XK_Shift_L ) {
directionKeyEvent = Key_Direction_L;
@@ -7838,8 +7986,10 @@ static Bool qt_keypress_scanner(Display *, XEvent *event, XPointer arg)
qt_auto_repeat_data *d = (qt_auto_repeat_data *) arg;
if (d->error ||
event->xkey.window != d->window ||
- event->xkey.keycode != d->keycode)
+ event->xkey.keycode != d->keycode) {
+ d->error = TRUE;
return FALSE;
+ }
if (event->type == XKeyPress) {
d->error = (! d->release || event->xkey.time - d->timestamp > 10);
@@ -7942,8 +8092,34 @@ bool TQETWidget::translateKeyEvent( const XEvent *event, bool grab )
translateKeyEventInternal( event, count, text, state, ascii, code, type );
}
+#ifndef TQT_NO_IM
+ TQInputContext *qic = getInputContext();
+#endif
+
// compress keys
if ( !text.isEmpty() && testWState(WState_CompressKeys) &&
+#ifndef TQT_NO_IM
+ // Ordinary input methods require discrete key events to work
+ // properly, so key compression has to be disabled when input
+ // context exists.
+ //
+ // And further consideration, some complex input method
+ // require all key press/release events discretely even if
+ // the input method awares of key compression and compressed
+ // keys are ordinary alphabets. For example, the uim project
+ // is planning to implement "combinational shift" feature for
+ // a Japanese input method, uim-skk. It will work as follows.
+ //
+ // 1. press "r"
+ // 2. press "u"
+ // 3. release both "r" and "u" in arbitrary order
+ // 4. above key sequence generates "Ru"
+ //
+ // Of course further consideration about other participants
+ // such as key repeat mechanism is required to implement such
+ // feature.
+ ! qic &&
+#endif // TQT_NO_IM
// do not compress keys if the key event we just got above matches
// one of the key ranges used to compute stopCompression
! ( ( code >= Key_Escape && code <= Key_SysReq ) ||
@@ -8002,7 +8178,12 @@ bool TQETWidget::translateKeyEvent( const XEvent *event, bool grab )
// autorepeat compression makes sense for all widgets (Windows
// does it automatically .... )
- if ( event->type == XKeyPress && text.length() <= 1 ) {
+ if ( event->type == XKeyPress && text.length() <= 1
+#ifndef TQT_NO_IM
+ // input methods need discrete key events
+ && ! qic
+#endif// TQT_NO_IM
+ ) {
XEvent dummy;
for (;;) {
@@ -8210,6 +8391,21 @@ bool TQETWidget::translateScrollDoneEvent( const XEvent *event )
return FALSE;
}
+#if defined(TQ_C_CALLBACKS)
+extern "C" {
+#endif
+#ifndef TQT_NO_XSYNC
+static Bool qt_net_wm_sync_request_scanner(Display*, XEvent* event, XPointer arg)
+{
+ return (event->type == ClientMessage && event->xclient.window == *(Window*)arg
+ && event->xclient.message_type == qt_wm_protocols
+ && event->xclient.data.l[ 0 ] == qt_net_wm_sync_request );
+}
+#endif
+
+#if defined(TQ_C_CALLBACKS)
+}
+#endif
//
// ConfigureNotify (window move and resize) event translation
@@ -8241,6 +8437,7 @@ bool TQETWidget::translateConfigEvent( const XEvent *event )
if (! extra || extra->compress_events) {
// ConfigureNotify compression for faster opaque resizing
XEvent otherEvent;
+ int compressed_configs = 0;
while ( XCheckTypedWindowEvent( x11Display(), winId(), ConfigureNotify,
&otherEvent ) ) {
if ( qt_x11EventFilter( &otherEvent ) )
@@ -8261,7 +8458,18 @@ bool TQETWidget::translateConfigEvent( const XEvent *event )
newCPos.ry() = otherEvent.xconfigure.y +
otherEvent.xconfigure.border_width;
}
+ ++compressed_configs;
}
+#ifndef TQT_NO_XSYNC
+ // _NET_WM_SYNC_REQUEST compression
+ Window wid = winId();
+ while ( compressed_configs &&
+ XCheckIfEvent( x11Display(), &otherEvent,
+ qt_net_wm_sync_request_scanner, (XPointer)&wid ) ) {
+ handleSyncRequest( (void*)&otherEvent );
+ --compressed_configs;
+ }
+#endif
}
TQRect cr ( tqgeometry() );
@@ -8315,6 +8523,8 @@ bool TQETWidget::translateConfigEvent( const XEvent *event )
tqrepaint( !testWFlags(WResizeNoErase) || transbg );
}
+ incrementSyncCounter();
+
return TRUE;
}