summaryrefslogtreecommitdiffstats
path: root/tqtinterface/qt4/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'tqtinterface/qt4/src/kernel')
-rw-r--r--tqtinterface/qt4/src/kernel/qt_kernel.pri8
-rw-r--r--tqtinterface/qt4/src/kernel/tqapplication.cpp68
-rw-r--r--tqtinterface/qt4/src/kernel/tqapplication.h26
-rw-r--r--tqtinterface/qt4/src/kernel/tqapplication_x11.cpp754
-rw-r--r--tqtinterface/qt4/src/kernel/tqclipboard_x11.cpp18
-rw-r--r--tqtinterface/qt4/src/kernel/tqdesktopwidget_x11.cpp46
-rw-r--r--tqtinterface/qt4/src/kernel/tqdnd_x11.cpp138
-rw-r--r--tqtinterface/qt4/src/kernel/tqdragobject.cpp10
-rw-r--r--tqtinterface/qt4/src/kernel/tqdragobject.h3
-rw-r--r--tqtinterface/qt4/src/kernel/tqevent.cpp4
-rw-r--r--tqtinterface/qt4/src/kernel/tqfontdatabase.cpp34
-rw-r--r--tqtinterface/qt4/src/kernel/tqfontdatabase_x11.cpp8
-rw-r--r--tqtinterface/qt4/src/kernel/tqfontengine_x11.cpp17
-rw-r--r--tqtinterface/qt4/src/kernel/tqinputcontext.cpp856
-rw-r--r--tqtinterface/qt4/src/kernel/tqinputcontext.h143
-rw-r--r--tqtinterface/qt4/src/kernel/tqinputcontext_x11.cpp504
-rw-r--r--tqtinterface/qt4/src/kernel/tqnamespace.h92
-rw-r--r--tqtinterface/qt4/src/kernel/tqpaintdevice_x11.cpp15
-rw-r--r--tqtinterface/qt4/src/kernel/tqpixmap_x11.cpp593
-rw-r--r--tqtinterface/qt4/src/kernel/tqrichtext.cpp20
-rw-r--r--tqtinterface/qt4/src/kernel/tqrichtext_p.h3
-rw-r--r--tqtinterface/qt4/src/kernel/tqt_x11_p.h5
-rw-r--r--tqtinterface/qt4/src/kernel/tqwidget.cpp33
-rw-r--r--tqtinterface/qt4/src/kernel/tqwidget.h54
-rw-r--r--tqtinterface/qt4/src/kernel/tqwidget_x11.cpp521
25 files changed, 2901 insertions, 1072 deletions
diff --git a/tqtinterface/qt4/src/kernel/qt_kernel.pri b/tqtinterface/qt4/src/kernel/qt_kernel.pri
index aa76de0..f10ed74 100644
--- a/tqtinterface/qt4/src/kernel/qt_kernel.pri
+++ b/tqtinterface/qt4/src/kernel/qt_kernel.pri
@@ -34,7 +34,6 @@ kernel {
$$KERNEL_H/tqimage.h \
$$KERNEL_P/tqimageformatinterface_p.h \
$$KERNEL_H/tqimageformatplugin.h \
- $$KERNEL_P/tqinputcontext_p.h \
$$KERNEL_H/tqkeycode.h \
$$KERNEL_H/tqkeysequence.h \
$$KERNEL_H/tqlayout.h \
@@ -99,6 +98,12 @@ kernel {
$$KERNEL_CPP/tqfontengine_p.h \
$$KERNEL_CPP/tqtextlayout_p.h
+ unix:x11 {
+ HEADERS += $$KERNEL_H/tqinputcontext.h
+ } else {
+ HEADERS += $$KERNEL_P/tqinputcontext_p.h
+ }
+
win32:SOURCES += $$KERNEL_CPP/tqapplication_win.cpp \
$$KERNEL_CPP/tqclipboard_win.cpp \
$$KERNEL_CPP/tqcolor_win.cpp \
@@ -130,6 +135,7 @@ kernel {
$$KERNEL_CPP/tqdesktopwidget_x11.cpp \
$$KERNEL_CPP/tqeventloop_x11.cpp \
$$KERNEL_CPP/tqfont_x11.cpp \
+ $$KERNEL_CPP/tqinputcontext.cpp \
$$KERNEL_CPP/tqinputcontext_x11.cpp \
$$KERNEL_CPP/tqmotifdnd_x11.cpp \
$$KERNEL_CPP/tqpixmap_x11.cpp \
diff --git a/tqtinterface/qt4/src/kernel/tqapplication.cpp b/tqtinterface/qt4/src/kernel/tqapplication.cpp
index af193c9..74d2f08 100644
--- a/tqtinterface/qt4/src/kernel/tqapplication.cpp
+++ b/tqtinterface/qt4/src/kernel/tqapplication.cpp
@@ -4113,6 +4113,35 @@ void TQApplication::postEvent( TQObject *receiver, TQEvent *event )
};
}
+#if !defined(TQT_NO_IM)
+ // if this is one of the compressible IM events, do compression
+ else if ( event->type() == TQEvent::IMCompose ) {
+ l->last();
+ TQPostEvent * cur = 0;
+ for ( ;; ) {
+ while ( (cur=l->current()) != 0 &&
+ ( cur->receiver != receiver ||
+ cur->event == 0 ||
+ cur->event->type() != event->type() ||
+ cur->event->type() != TQEvent::IMStart ) )
+ l->prev();
+ if ( l->current() != 0 ) {
+ // IMCompose must not be compressed with another one
+ // beyond its IMStart boundary
+ if ( cur->event->type() == TQEvent::IMStart ) {
+ break;
+ } else if ( cur->event->type() == TQEvent::IMCompose ) {
+ TQIMComposeEvent * e = (TQIMComposeEvent *)(cur->event);
+ *e = *(TQIMComposeEvent *)event;
+ delete event;
+ return;
+ }
+ }
+ break;
+ };
+ }
+#endif
+
// if no compression could be done, just append something
event->posted = TRUE;
TQPostEvent * pe = new TQPostEvent( receiver, event );
@@ -4259,6 +4288,23 @@ void TQApplication::sendPostedEvents( TQObject *receiver, int event_type )
void TQApplication::removePostedEvents( TQObject *receiver )
{
+ removePostedEvents( receiver, 0 );
+}
+
+/*!
+ Removes all events that have the event type \a event_type posted
+ using postEvent() for \a receiver.
+
+ The events are \e not dispatched, instead they are removed from the
+ queue.
+
+ If \a event_type is 0, all the events are removed from the queue.
+
+ \threadsafe
+*/
+
+void TQApplication::removePostedEvents( TQObject *receiver, int event_type )
+{
if ( !receiver )
return;
@@ -4277,18 +4323,24 @@ void TQApplication::removePostedEvents( TQObject *receiver )
// leave the TQPostEvent objects; they'll be deleted by
// sendPostedEvents().
TQPostEventList * l = receiver->postedEvents;
- receiver->postedEvents = 0;
l->first();
TQPostEvent * pe;
while( (pe=l->current()) != 0 ) {
- if ( pe->event ) {
- pe->event->posted = FALSE;
- delete pe->event;
- pe->event = 0;
+ if ( !event_type || pe->event->type() == event_type ) {
+ if ( pe->event ) {
+ pe->event->posted = FALSE;
+ delete pe->event;
+ pe->event = 0;
+ }
+ l->remove();
+ } else {
+ l->next();
}
- l->remove();
}
- delete l;
+ if ( !event_type || !l->count() ) {
+ receiver->postedEvents = 0;
+ delete l;
+ }
}
@@ -4473,6 +4525,8 @@ void TQApplication::setActiveWindow( TQWidget* act )
focus_widget = 0;
#ifdef TQ_WS_WIN
TQInputContext::accept( tmp );
+#elif defined(TQ_WS_X11)
+ tmp->unfocusInputContext();
#endif
TQApplication::sendSpontaneousEvent( tmp, &out );
} else if ( active_window ) {
diff --git a/tqtinterface/qt4/src/kernel/tqapplication.h b/tqtinterface/qt4/src/kernel/tqapplication.h
index 2be7c02..e5e2ea9 100644
--- a/tqtinterface/qt4/src/kernel/tqapplication.h
+++ b/tqtinterface/qt4/src/kernel/tqapplication.h
@@ -67,6 +67,9 @@ class TQSessionManager;
class TQStyle;
class TQTranslator;
class TQEventLoop;
+#if defined(TQ_WS_X11)
+class TQIMEvent;
+#endif
#if defined(TQ_WS_TQWS)
class TQWSDecoration;
#endif
@@ -467,8 +470,19 @@ public:
virtual void saveState( TQSessionManager& sm );
#endif
#if defined(TQ_WS_X11)
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ virtual TQWidget *locateICHolderWidget( TQWidget *w );
+ virtual TQWidgetList *icHolderWidgets();
+ static void create_im();
+ static void close_im();
+#else
+ TQWidget *locateICHolderWidget( TQWidget *w );
+ TQWidgetList *icHolderWidgets();
static void create_xim();
static void close_xim();
+#endif
+ static TQString defaultInputMethod();
+ void changeAllInputContext( const TQString & );
static bool x11_apply_settings();
#endif
void wakeUpGuiThread();
@@ -523,6 +537,12 @@ private:
friend void qt_init(int *, char **, TQApplication::Type);
#endif
+#if defined(TQ_WS_X11)
+private slots:
+ void postIMEvent( TQObject *receiver, TQIMEvent *event );
+#endif
+
+private:
#ifdef TQT_THREAD_SUPPORT
static TQMutex *qt_mutex;
#endif // TQT_THREAD_SUPPORT
@@ -572,9 +592,12 @@ private:
static TQString* session_key;
bool is_session_restored;
#endif
-#if defined(TQ_WS_X11) && !defined (TQT_NO_STYLE )
+#if defined(TQ_WS_X11)
+#if !defined (TQT_NO_STYLE)
static void x11_initialize_style();
#endif
+ static TQString defaultIM; // default input method's name in this application.
+#endif
static TQSize app_strut;
#ifndef TQT_NO_COMPONENT
@@ -591,6 +614,7 @@ private:
static bool sendSpontaneousEvent( TQObject *receiver, TQEvent *event );
static void removePostedEvent( TQEvent * );
+ static void removePostedEvents( TQObject *receiver, int event_type );
friend class TQWidget;
friend class TQETWidget;
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;
}
diff --git a/tqtinterface/qt4/src/kernel/tqclipboard_x11.cpp b/tqtinterface/qt4/src/kernel/tqclipboard_x11.cpp
index 14e7f08..9fd90e4 100644
--- a/tqtinterface/qt4/src/kernel/tqclipboard_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqclipboard_x11.cpp
@@ -111,6 +111,7 @@ static int pending_timer_id = 0;
static bool pending_clipboard_changed = FALSE;
static bool pending_selection_changed = FALSE;
+TQ_EXPORT bool qt_qclipboard_bailout_hack = false;
// event capture mechanism for qt_xclb_wait_for_event
static bool waiting_for_data = FALSE;
@@ -142,6 +143,15 @@ static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer)
|| e->xselectionclear.selection == qt_xa_clipboard)));
}
+static bool selection_request_pending = false;
+
+static Bool check_selection_request_pending( Display*, XEvent* e, XPointer )
+ {
+ if( e->type == SelectionRequest && e->xselectionrequest.owner == owner->winId())
+ selection_request_pending = true;
+ return False;
+ }
+
bool qt_xclb_wait_for_event( Display *dpy, Window win, int type, XEvent *event,
int timeout )
{
@@ -193,6 +203,14 @@ bool qt_xclb_wait_for_event( Display *dpy, Window win, int type, XEvent *event,
do {
if ( XCheckTypedWindowEvent(dpy,win,type,event) )
return TRUE;
+ if( qt_qclipboard_bailout_hack ) {
+ XEvent dummy;
+ selection_request_pending = false;
+ if ( owner != NULL )
+ XCheckIfEvent(dpy,&dummy,check_selection_request_pending,NULL);
+ if( selection_request_pending )
+ return TRUE;
+ }
// process other clipboard events, since someone is probably requesting data from us
XEvent e;
diff --git a/tqtinterface/qt4/src/kernel/tqdesktopwidget_x11.cpp b/tqtinterface/qt4/src/kernel/tqdesktopwidget_x11.cpp
index e2bd9f9..84da179 100644
--- a/tqtinterface/qt4/src/kernel/tqdesktopwidget_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqdesktopwidget_x11.cpp
@@ -111,7 +111,7 @@ TQDesktopWidgetPrivate::~TQDesktopWidgetPrivate()
screens[i] = 0;
}
- delete [] screens;
+ free(screens);
}
if ( rects ) delete [] rects;
@@ -121,6 +121,8 @@ TQDesktopWidgetPrivate::~TQDesktopWidgetPrivate()
void TQDesktopWidgetPrivate::init()
{
// get the screen count
+ int newScreenCount;
+
#ifndef TQT_NO_XINERAMA
XineramaScreenInfo *xinerama_screeninfo = 0;
int unused;
@@ -130,23 +132,26 @@ void TQDesktopWidgetPrivate::init()
if (use_xinerama) {
xinerama_screeninfo =
- XineramaQueryScreens(TQPaintDevice::x11AppDisplay(), &screenCount);
+ XineramaQueryScreens(TQPaintDevice::x11AppDisplay(), &newScreenCount);
+
+ if (xinerama_screeninfo)
defaultScreen = 0;
} else
#endif // TQT_NO_XINERAMA
{
defaultScreen = DefaultScreen(TQPaintDevice::x11AppDisplay());
- screenCount = ScreenCount(TQPaintDevice::x11AppDisplay());
+ newScreenCount = ScreenCount(TQPaintDevice::x11AppDisplay());
+ use_xinerama = false;
}
delete [] rects;
- rects = new TQRect[ screenCount ];
+ rects = new TQRect[ newScreenCount ];
delete [] workareas;
- workareas = new TQRect[ screenCount ];
+ workareas = new TQRect[ newScreenCount ];
// get the tqgeometry of each screen
- int i, x, y, w, h;
- for ( i = 0; i < screenCount; i++ ) {
+ int i, j, x, y, w, h;
+ for ( i = 0, j = 0; i < newScreenCount; i++ ) {
#ifndef TQT_NO_XINERAMA
if (use_xinerama) {
@@ -163,11 +168,33 @@ void TQDesktopWidgetPrivate::init()
h = HeightOfScreen(ScreenOfDisplay(TQPaintDevice::x11AppDisplay(), i));
}
- rects[i].setRect(x, y, w, h);
workareas[i] = TQRect();
+ rects[j].setRect(x, y, w, h);
+
+ // overlapping?
+ if (j > 0 && rects[j-1].intersects(rects[j])) {
+ // pick the bigger one, ignore the other
+ if ((rects[j].width()*rects[j].height()) >
+ (rects[j-1].width()*rects[j-1].height()))
+ rects[j-1] = rects[j];
+ }
+ else
+ j++;
}
+ if (screens) {
+ // leaks TQWidget* pointers on purpose, can't delete them as pointer escapes
+ screens = (TQWidget**) realloc(screens, j * sizeof(TQWidget*));
+ if (j > screenCount)
+ memset(&screens[screenCount], 0, (j-screenCount) * sizeof(TQWidget*));
+ }
+
+ screenCount = j;
+
#ifndef TQT_NO_XINERAMA
+ if (use_xinerama && screenCount == 1)
+ use_xinerama = false;
+
if (xinerama_screeninfo)
XFree(xinerama_screeninfo);
#endif // TQT_NO_XINERAMA
@@ -220,8 +247,7 @@ TQWidget *TQDesktopWidget::screen( int screen )
screen = d->defaultScreen;
if ( ! d->screens ) {
- d->screens = new TQWidget*[ d->screenCount ];
- memset( d->screens, 0, d->screenCount * sizeof( TQWidget * ) );
+ d->screens = (TQWidget**) calloc( d->screenCount, sizeof(TQWidget*));
d->screens[ d->defaultScreen ] = this;
}
diff --git a/tqtinterface/qt4/src/kernel/tqdnd_x11.cpp b/tqtinterface/qt4/src/kernel/tqdnd_x11.cpp
index 7882349..3ba66b9 100644
--- a/tqtinterface/qt4/src/kernel/tqdnd_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqdnd_x11.cpp
@@ -52,13 +52,15 @@
#include "tqdragobject.h"
#include "tqobjectlist.h"
#include "tqcursor.h"
+#include "tqbitmap.h"
+#include "tqpainter.h"
#include "tqt_x11_p.h"
// conflict resolution
-// unused, may be used again later: const int XKeyPress = KeyPress;
-// unused, may be used again later: const int XKeyRelease = KeyRelease;
+const int XKeyPress = KeyPress;
+const int XKeyRelease = KeyRelease;
#undef KeyPress
#undef KeyRelease
@@ -114,6 +116,8 @@ Atom qt_xdnd_finished;
Atom qt_xdnd_type_list;
const int qt_xdnd_version = 4;
+extern int qt_x11_translateButtonState( int s );
+
// Actions
//
// The Xdnd spec allows for user-defined actions. This could be implemented
@@ -199,6 +203,8 @@ static Time qt_xdnd_target_current_time;
static int qt_xdnd_current_screen = -1;
// state of dragging... true if dragging, false if not
bool qt_xdnd_dragging = FALSE;
+// need to check state of keyboard modifiers
+static bool need_modifiers_check = FALSE;
// dict of payload data, sorted by type atom
static TQIntDict<TQByteArray> * qt_xdnd_target_data = 0;
@@ -257,21 +263,49 @@ class TQShapedPixmapWidget : public TQWidget {
public:
TQShapedPixmapWidget(int screen = -1) :
TQWidget(TQApplication::desktop()->screen( screen ),
- 0, (Qt::WindowType)(WStyle_Customize | WStyle_Tool | WStyle_NoBorder | WX11BypassWM) )
+ 0, (Qt::WindowType)(WStyle_Customize | WStyle_Tool | WStyle_NoBorder | WX11BypassWM) ), oldpmser( 0 ), oldbmser( 0 )
{
+ x11SetWindowType( X11WindowTypeDND );
}
- void setPixmap(TQPixmap pm)
+ void setPixmap(TQPixmap pm, TQPoint hot)
{
- const TQBitmap* mask = pm.tqmask();
- if ( mask ) {
+ int bmser = pm.tqmask() ? pm.tqmask()->serialNumber() : 0;
+ if( oldpmser == pm.serialNumber() && oldbmser == bmser
+ && oldhot == hot )
+ return;
+ oldpmser = pm.serialNumber();
+ oldbmser = bmser;
+ oldhot = hot;
+ bool hotspot_in = !(hot.x() < 0 || hot.y() < 0 || hot.x() >= pm.width() || hot.y() >= pm.height());
+// if the pixmap has hotspot in its area, make a "hole" in it at that position
+// this will allow XTranslateCoordinates() to find directly the window below the cursor instead
+// of finding this pixmap, and therefore there won't be needed any (slow) search for the window
+// using findRealWindow()
+ if( hotspot_in ) {
+ TQBitmap tqmask = pm.tqmask() ? *pm.tqmask() : TQBitmap( pm.width(), pm.height());
+ if( !pm.tqmask())
+ tqmask.fill( TQt::color1 );
+ TQPainter p( &tqmask );
+ p.setPen( TQt::color0 );
+ p.drawPoint( hot.x(), hot.y());
+ p.end();
+ pm.setMask( tqmask );
+ setMask( tqmask );
+ } else if ( pm.tqmask() ) {
setMask( *mask );
} else {
clearMask();
}
resize(pm.width(),pm.height());
setErasePixmap(pm);
+ erase();
}
+
+private:
+ int oldpmser;
+ int oldbmser;
+ TQPoint oldhot;
};
static TQShapedPixmapWidget * qt_xdnd_deco = 0;
@@ -875,8 +909,59 @@ void qt_handle_xdnd_finished( TQWidget *, const XEvent * xe, bool passive )
void TQDragManager::timerEvent( TQTimerEvent* e )
{
- if ( e->timerId() == heartbeat && qt_xdnd_source_sameanswer.isNull() )
- move( TQCursor::pos() );
+ if ( e->timerId() == heartbeat ) {
+ if( need_modifiers_check ) {
+ Window root, child;
+ int root_x, root_y, win_x, win_y;
+ unsigned int tqmask;
+ XQueryPointer( qt_xdisplay(), qt_xrootwin( qt_xdnd_current_screen ),
+ &root, &child, &root_x, &root_y, &win_x, &win_y, &tqmask );
+ if( updateMode( (ButtonState)qt_x11_translateButtonState( tqmask )))
+ qt_xdnd_source_sameanswer = TQRect(); // force move
+ }
+ need_modifiers_check = TRUE;
+ if( qt_xdnd_source_sameanswer.isNull() )
+ move( TQCursor::pos() );
+ }
+}
+
+static bool qt_xdnd_was_move = false;
+static bool qt_xdnd_found = false;
+// check whole incoming X queue for move events
+// checking whole queue is done by always returning False in the predicate
+// if there's another move event in the queue, and there's not a mouse button
+// or keyboard or ClientMessage event before it, the current move event
+// may be safely discarded
+// this helps avoiding being overloaded by being flooded from many events
+// from the XServer
+static
+Bool qt_xdnd_predicate( Display*, XEvent* ev, XPointer )
+{
+ if( qt_xdnd_found )
+ return False;
+ if( ev->type == MotionNotify )
+ {
+ qt_xdnd_was_move = true;
+ qt_xdnd_found = true;
+ }
+ if( ev->type == ButtonPress || ev->type == ButtonRelease
+ || ev->type == XKeyPress || ev->type == XKeyRelease
+ || ev->type == ClientMessage )
+ {
+ qt_xdnd_was_move = false;
+ qt_xdnd_found = true;
+ }
+ return False;
+}
+
+static
+bool qt_xdnd_another_movement()
+{
+ qt_xdnd_was_move = false;
+ qt_xdnd_found = false;
+ XEvent dummy;
+ XCheckIfEvent( qt_xdisplay(), &dummy, qt_xdnd_predicate, NULL );
+ return qt_xdnd_was_move;
}
bool TQDragManager::eventFilter( TQObject * o, TQEvent * e)
@@ -901,8 +986,11 @@ bool TQDragManager::eventFilter( TQObject * o, TQEvent * e)
if ( e->type() == TQEvent::MouseMove ) {
TQMouseEvent* me = (TQMouseEvent *)e;
- updateMode(me->stateAfter());
- move( me->globalPos() );
+ if( !qt_xdnd_another_movement()) {
+ updateMode(me->stateAfter());
+ move( me->globalPos() );
+ }
+ need_modifiers_check = FALSE;
return TRUE;
} else if ( e->type() == TQEvent::MouseButtonRelease ) {
tqApp->removeEventFilter( this );
@@ -941,9 +1029,11 @@ bool TQDragManager::eventFilter( TQObject * o, TQEvent * e)
beingCancelled = FALSE;
tqApp->exit_loop();
} else {
- updateMode(ke->stateAfter());
- qt_xdnd_source_sameanswer = TQRect(); // force move
- move( TQCursor::pos() );
+ if( updateMode(ke->stateAfter())) {
+ qt_xdnd_source_sameanswer = TQRect(); // force move
+ move( TQCursor::pos() );
+ }
+ need_modifiers_check = FALSE;
}
return TRUE; // Eat all key events
}
@@ -970,10 +1060,10 @@ bool TQDragManager::eventFilter( TQObject * o, TQEvent * e)
static TQt::ButtonState oldstate;
-void TQDragManager::updateMode( TQt::ButtonState newstate )
+bool TQDragManager::updateMode( TQt::ButtonState newstate )
{
if ( newstate == oldstate )
- return;
+ return false;
const int both = ShiftButton|ControlButton;
if ( (newstate & both) == both ) {
global_requested_action = TQDropEvent::Link;
@@ -997,6 +1087,7 @@ void TQDragManager::updateMode( TQt::ButtonState newstate )
}
}
oldstate = newstate;
+ return true;
}
@@ -1138,12 +1229,13 @@ void TQDragManager::move( const TQPoint & globalPos )
// recreate the pixmap on the new screen...
delete qt_xdnd_deco;
qt_xdnd_deco = new TQShapedPixmapWidget( screen );
+ qt_xdnd_deco->x11SetWindowTransient( dragSource->tqtopLevelWidget());
if (!TQWidget::mouseGrabber()) {
updatePixmap();
qt_xdnd_deco->grabMouse();
}
}
- updatePixmap();
+ updatePixmap( globalPos );
if ( qt_xdnd_source_sameanswer.contains( globalPos ) &&
qt_xdnd_source_sameanswer.isValid() ) {
@@ -1691,6 +1783,7 @@ bool TQDragManager::drag( TQDragObject * o, TQDragObject::DragMode mode )
dragSource = (TQWidget *)(object->tqparent());
+ qt_xdnd_deco->x11SetWindowTransient( dragSource->tqtopLevelWidget());
tqApp->installEventFilter( this );
qt_xdnd_source_current_time = GET_QT_X_TIME();
XSetSelectionOwner( TQPaintDevice::x11AppDisplay(), qt_xdnd_selection,
@@ -1703,6 +1796,7 @@ bool TQDragManager::drag( TQDragObject * o, TQDragObject::DragMode mode )
qt_xdnd_source_sameanswer = TQRect();
move(TQCursor::pos());
heartbeat = startTimer(200);
+ need_modifiers_check = FALSE;
#ifndef TQT_NO_CURSOR
tqApp->setOverrideCursor( Qt::ArrowCursor );
@@ -1736,7 +1830,7 @@ bool TQDragManager::drag( TQDragObject * o, TQDragObject::DragMode mode )
// qt_xdnd_source_object persists until we get an xdnd_finish message
}
-void TQDragManager::updatePixmap()
+void TQDragManager::updatePixmap( const TQPoint& cursorPos )
{
if ( qt_xdnd_deco ) {
TQPixmap pm;
@@ -1751,9 +1845,8 @@ void TQDragManager::updatePixmap()
defaultPm = new TQPixmap(default_pm);
pm = *defaultPm;
}
- qt_xdnd_deco->setPixmap(pm);
- qt_xdnd_deco->move(TQCursor::pos()-pm_hot);
- qt_xdnd_deco->tqrepaint(FALSE);
+ qt_xdnd_deco->setPixmap(pm, pm_hot);
+ qt_xdnd_deco->move(cursorPos-pm_hot);
//if ( willDrop ) {
qt_xdnd_deco->show();
//} else {
@@ -1762,4 +1855,9 @@ void TQDragManager::updatePixmap()
}
}
+void TQDragManager::updatePixmap()
+{
+ updatePixmap( TQCursor::pos());
+}
+
#endif // TQT_NO_DRAGANDDROP
diff --git a/tqtinterface/qt4/src/kernel/tqdragobject.cpp b/tqtinterface/qt4/src/kernel/tqdragobject.cpp
index 6e58f84..5a4d2fe 100644
--- a/tqtinterface/qt4/src/kernel/tqdragobject.cpp
+++ b/tqtinterface/qt4/src/kernel/tqdragobject.cpp
@@ -2468,6 +2468,16 @@ bool TQTextDrag::decode( const TQMimeSource* e, TQString& str, TQCString& subtyp
{
if(!e)
return FALSE;
+
+ // when subtype is not specified, try text/plain first, otherwise this may read
+ // things like text/x-moz-url even though better targets are available
+ if( subtype.isNull()) {
+ TQCString subtmp = "plain";
+ if( decode( e, str, subtmp )) {
+ subtype = subtmp;
+ return true;
+ }
+ }
if ( e->cacheType == TQMimeSource::Text ) {
str = *e->cache.txt.str;
diff --git a/tqtinterface/qt4/src/kernel/tqdragobject.h b/tqtinterface/qt4/src/kernel/tqdragobject.h
index 3d55967..7133c0f 100644
--- a/tqtinterface/qt4/src/kernel/tqdragobject.h
+++ b/tqtinterface/qt4/src/kernel/tqdragobject.h
@@ -476,10 +476,11 @@ private:
void move( const TQPoint & );
void drop();
void updatePixmap();
+ void updatePixmap( const TQPoint& cursorPos );
private:
TQDragObject * object;
- void updateMode( TQt::ButtonState newstate );
+ bool updateMode( TQt::ButtonState newstate );
void updateCursor();
#if defined(TQ_WS_X11)
void createCursors();
diff --git a/tqtinterface/qt4/src/kernel/tqevent.cpp b/tqtinterface/qt4/src/kernel/tqevent.cpp
index b34f38d..59a6ca7 100644
--- a/tqtinterface/qt4/src/kernel/tqevent.cpp
+++ b/tqtinterface/qt4/src/kernel/tqevent.cpp
@@ -874,6 +874,10 @@ TQWheelEvent::TQWheelEvent( const TQPoint &pos, int delta, int state, Orientatio
the result of a known key (e.g. it may be the result of a compose
sequence or a keyboard macro, or due to key event compression).
+ Applications should not use the TQt latin 1 keycodes between 128
+ and 255, but should rather use the TQKeyEvent::text(). This is
+ mainly for compatibility.
+
\sa TQWidget::setKeyCompression()
*/
diff --git a/tqtinterface/qt4/src/kernel/tqfontdatabase.cpp b/tqtinterface/qt4/src/kernel/tqfontdatabase.cpp
index f79c14b..e70be03 100644
--- a/tqtinterface/qt4/src/kernel/tqfontdatabase.cpp
+++ b/tqtinterface/qt4/src/kernel/tqfontdatabase.cpp
@@ -707,6 +707,10 @@ static TQtFontStyle *bestStyle(TQtFontFoundry *foundry, const TQtFontStyle::Key
}
FM_DEBUG( " best style has distance 0x%x", dist );
+ if (!foundry->count) {
+ TQtFontStyle *temp = NULL;
+ return temp;
+ }
return foundry->styles[best];
}
@@ -980,20 +984,22 @@ TQFontDatabase::tqfindFont( TQFont::Script script, const TQFontPrivate *fp,
#ifdef TQ_WS_X11
if (script == TQFont::Han) {
- // modify script according to locale
- static TQFont::Script defaultHan = TQFont::UnknownScript;
- if (defaultHan == TQFont::UnknownScript) {
- TQCString locale = setlocale(LC_ALL, NULL);
- if (locale.tqcontains("ko"))
- defaultHan = TQFont::Han_Korean;
- else if (locale.tqcontains("zh_TW") || locale.tqcontains("zh_HK"))
- defaultHan = TQFont::Han_TraditionalChinese;
- else if (locale.tqcontains("zh"))
- defaultHan = TQFont::Han_SimplifiedChinese;
- else
- defaultHan = TQFont::Han_Japanese;
- }
- script = defaultHan;
+ // modify script according to locale
+ static TQFont::Script defaultHan;
+ TQCString locale = setlocale(LC_ALL, NULL);
+
+ if (locale.tqcontains("ko"))
+ defaultHan = TQFont::Han_Korean;
+ else if (locale.tqcontains("zh_TW") || locale.tqcontains("zh_HK"))
+ defaultHan = TQFont::Han_TraditionalChinese;
+ else if (locale.tqcontains("zh"))
+ defaultHan = TQFont::Han_SimplifiedChinese;
+ else if (locale.tqcontains("ja"))
+ defaultHan = TQFont::Han_Japanese;
+ else
+ defaultHan = TQFont::Han; // don't change
+
+ script = defaultHan;
}
#endif
diff --git a/tqtinterface/qt4/src/kernel/tqfontdatabase_x11.cpp b/tqtinterface/qt4/src/kernel/tqfontdatabase_x11.cpp
index 8ea403f..97cb544 100644
--- a/tqtinterface/qt4/src/kernel/tqfontdatabase_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqfontdatabase_x11.cpp
@@ -721,6 +721,9 @@ static void loadXlfds( const char *reqFamily, int encoding_id )
if ( fontFamily && fontFamily->xlfdLoaded )
return;
+#ifdef TQT_XFT2
+ if ( !qt_has_xft ) {
+#endif // TQT_XFT2
int fontCount;
// force the X server to give us XLFDs
TQCString xlfd_pattern = "-*-";
@@ -822,8 +825,11 @@ static void loadXlfds( const char *reqFamily, int encoding_id )
}
XFreeFontNames( fontList );
-}
+#ifdef TQT_XFT2
+ }
+#endif // TQT_XFT2
+}
#ifndef TQT_NO_XFTFREETYPE
static int getXftWeight(int xftweight)
diff --git a/tqtinterface/qt4/src/kernel/tqfontengine_x11.cpp b/tqtinterface/qt4/src/kernel/tqfontengine_x11.cpp
index 0b45ec9..8d76e0b 100644
--- a/tqtinterface/qt4/src/kernel/tqfontengine_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqfontengine_x11.cpp
@@ -2694,23 +2694,16 @@ bool TQOpenType::positionAndAdd(TQShaperItem *item, bool doLogClusters)
// ###### fix the case where we have y advances. How do we handle this in Uniscribe?????
if (positions[i].new_advance) {
item->advances[i] = item->flags & TQTextEngine::RightToLeft
- ? -tqRound((positions[i].x_advance >> 6)*scale)
+ ? -tqRound((positions[i].x_advance >> 6)*scale)
: tqRound((positions[i].x_advance >> 6)*scale);
} else {
item->advances[i] += item->flags & TQTextEngine::RightToLeft
- ? -tqRound((positions[i].x_advance >> 6)*scale)
+ ? -tqRound((positions[i].x_advance >> 6)*scale)
: tqRound((positions[i].x_advance >> 6)*scale);
}
- int back = 0;
- item->offsets[i].x = tqRound((positions[i].x_pos >> 6)*scale);
- item->offsets[i].y = tqRound((positions[i].y_pos >> 6)*scale);
- while (positions[i-back].back) {
- back += positions[i - back].back;
- item->offsets[i].x += tqRound((positions[i - back].x_pos >> 6)*scale);
- item->offsets[i].y += tqRound((positions[i - back].y_pos >> 6)*scale);
- }
- item->offsets[i].y = -item->offsets[i].y;
- back = positions[i].back;
+ item->offsets[i].x = tqRound((positions[i].x_pos >> 6)*scale);
+ item->offsets[i].y = -tqRound((positions[i].y_pos >> 6)*scale);
+ int back = positions[i].back;
if (item->flags & TQTextEngine::RightToLeft) {
while (back--) {
item->offsets[i].x -= item->advances[i-back];
diff --git a/tqtinterface/qt4/src/kernel/tqinputcontext.cpp b/tqtinterface/qt4/src/kernel/tqinputcontext.cpp
new file mode 100644
index 0000000..dfb38f7
--- /dev/null
+++ b/tqtinterface/qt4/src/kernel/tqinputcontext.cpp
@@ -0,0 +1,856 @@
+/****************************************************************************
+** $Id: qinputcontext.cpp,v 1.6 2004/06/22 06:47:30 daisuke Exp $
+**
+** Implementation of TQInputContext class
+**
+** Copyright (C) 2000-2003 Trolltech AS. All rights reserved.
+**
+** This file is part of the kernel module of the TQt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.TQPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid TQt Enterprise Edition or TQt Professional Edition
+** licenses for Unix/X11 may use this file in accordance with the TQt Commercial
+** License Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about TQt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for TQPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+//#define TQT_NO_IM_PREEDIT_RELOCATION
+
+#include "tqinputcontext.h"
+
+#ifndef TQT_NO_IM
+
+#include "tqplatformdefs.h"
+
+#include "tqapplication.h"
+#include "tqwidget.h"
+#include "tqpopupmenu.h"
+
+#include <stdlib.h>
+#include <limits.h>
+
+class TQInputContextPrivate
+{
+public:
+ TQInputContextPrivate()
+ : holderWidget( 0 ), composingWidget( 0 ), hasFocus( FALSE ),
+ isComposing( FALSE )
+#if !defined(TQT_NO_IM_PREEDIT_RELOCATION)
+ , preeditString( TQString() ),
+ cursorPosition( -1 ), selLength ( 0 )
+#endif
+ {}
+
+ TQWidget *holderWidget; // widget to which TQInputContext instance belongs.
+ TQWidget *composingWidget;
+ bool hasFocus;
+ bool isComposing;
+
+ void updateComposingState( const TQString &text,
+ int newCursorPosition, int newSelLength ) {
+#if !defined(TQT_NO_IM_PREEDIT_RELOCATION)
+ preeditString = text;
+ cursorPosition = newCursorPosition;
+ selLength = newSelLength;
+#endif
+ }
+
+ void resetComposingState() {
+ isComposing = FALSE;
+#if !defined(TQT_NO_IM_PREEDIT_RELOCATION)
+ preeditString = TQString();
+ cursorPosition = -1;
+ selLength = 0;
+#endif
+ }
+
+#if !defined(TQT_NO_IM_PREEDIT_RELOCATION)
+ TQString preeditString;
+ int cursorPosition;
+ int selLength;
+#endif
+};
+
+
+// UPDATED COMMENT RETQUIRED -- 2004-07-08 YamaKen
+/*!
+ \class TQInputContext qinputcontext.h
+ \brief The TQInputContext class abstracts the input method dependent data and composing state.
+
+ \ingroup i18n
+
+ An input method is responsible to input complex text that cannot
+ be inputted via simple keymap. It converts a sequence of input
+ events (typically key events) into a text string through the input
+ method specific converting process. The class of the processes are
+ widely ranging from simple finite state machine to complex text
+ translator that pools a whole paragraph of a text with text
+ editing capability to perform grammar and semantic analysis.
+
+ To abstract such different input method specific intermediate
+ information, TQt offers the TQInputContext as base class. The
+ concept is well known as 'input context' in the input method
+ domain. an input context is created for a text widget in response
+ to a demand. It is ensured that an input context is prepared for
+ an input method before input to a text widget.
+
+ Multiple input contexts that is belonging to a single input method
+ may concurrently coexist. Suppose multi-window text editor. Each
+ text widget of window A and B holds different TQInputContext
+ instance which contains different state information such as
+ partially composed text.
+
+ \section1 Groups of functions:
+
+ \table
+ \header \i Context \i Functions
+
+ \row \i Receiving information \i
+ x11FilterEvent(),
+ filterEvent(),
+ setMicroFocus(),
+ mouseHandler()
+
+ \row \i Sending back composed text \i
+ sendIMEvent(),
+
+ \row \i State change notification \i
+ setFocus(),
+ unsetFocus(),
+ reset()
+
+ \row \i Context information \i
+ identifierName(),
+ language(),
+ font(),
+ isComposing(),
+
+ \endtable
+
+
+ \section1 Sharing input context between text widgets
+
+ Any input context can be shared between several text widgets to
+ reduce resource consumption. In ideal case, each text widgets
+ should be allocated dedicated input context. But some complex
+ input contexts require slightly heavy resource such as 100
+ kilobytes of memory. It prevents quite many text widgets from
+ being used concurrently.
+
+ To resolve such problem, we can share an input context. There is
+ one 'input context holder widget' per text widgets that shares
+ identical input context. In this model, the holder widget owns the
+ shared input context. Other text widgets access the input context
+ via TQApplication::locateICHolderWidget(). But the access
+ convention is transparently hidden into TQWidget, so developers are
+ not required to aware of it.
+
+ What developer should know is only the mapping function
+ TQApplication::locateICHolderWidget(). It accepts a widget as
+ argument and returns its holder widget. Default implementation
+ returns the top-level widget of the widget as reasonable
+ assumption. But some applications should reimplement the function
+ to fit application specific usability. See
+ TQApplication::locateICHolderWidget() for further information.
+
+
+ \section1 Preedit preservation
+
+ As described above, input contexts have wide variety of amount of
+ the state information in accordance with belonging input
+ method. It is ranging from 2-3 keystrokes of sequence in
+ deterministic input methods to hundreds of keystrokes with
+ semantic text refinement in complex input methods such as ordinary
+ Japanese input method. The difference requires the different reset
+ policies in losing input focus.
+
+ The former simple input method case, users will prefer resetting
+ the context to back to the neutral state when something
+ happened. Suppose a web browsing. The user scroll the page by
+ scrollbar after he or she has typed a half of the valid key
+ sequence into a text widget. In the case, the input context should
+ be reset in losing focus when he or she has dragged the
+ scrollbar. He or she will be confused if the input context is
+ still preserved until focused back to the text widget because he
+ or she will restart typing with first key of the sequence as a
+ habitual operation.
+
+ On the other hand, we should choose completely different policy
+ for the latter complex input method case. Suppose same situation
+ as above but he or she is using a complex input method. In the
+ case, he or she will be angry if the input context has been lost
+ when he or she has dragged the scrollbar because the input context
+ contained a valuably composed text made up by considerable input
+ cost. So we should not reset the input context in the case. And
+ the input context should be preserved until focused back to the
+ text widget. This behavior is named as 'preedit preservation'.
+
+ The two policies can be switched by calling or not calling reset()
+ in unsetFocus(). Default implementation of unsetFocus() calls
+ reset() to fit the simple input methods. The implementation is
+ expressed as 'preedit preservation is disabled'.
+
+
+ \section1 Preedit relocation
+
+ Although the most case of the preedit preservation problem for
+ complex input methods is resolved as described above, there is a
+ special case. Suppose the case that matches all of the following
+ conditions.
+
+ \list
+
+ \i a input focus has been moved from a text widget to another text
+ widget directly
+
+ \i the input context is shared between the two text widgets
+
+ \i preedit preservation is enabled for the input context
+
+ \endlist
+
+ In the case, there are the following two requirements that
+ contradicts each other. The input context sharing causes it.
+
+ \list
+
+ \i the input context has to be reset to prepare to input to the
+ newly focused text widget
+
+ \i the input context has to be preserved until focused back to the
+ previous text widget
+
+ \endlist
+
+ A intrinsic feature named 'preedit relocation' is available to
+ compromise the requirements. If the feature is enabled for the
+ input context, it is simply moved to the new text widget with the
+ preedit string. The user continues the input on the new text
+ widget, or relocate it to another text widget. The preedit of
+ previous text widget is automatically cleared to back to the
+ neutral state of the widget.
+
+ This strange behavior is just a compromise. As described in
+ previous section, complex input method user should not be exposed
+ to the risk losing the input context because it contains valuable
+ long text made up with considerable input cost. The user will
+ immediately focus back to the previous text widget to continue the
+ input in the correct text widget if the preedit relocation
+ occurred. The feature is mainly existing as safety.
+
+ The feature properly works even if the focus is moved as
+ following. Input method developers are not required to be aware of
+ the relocation protocol since TQInputContext transparently handles
+ it.
+
+ a text widget -> a non-text widget -> another text widget
+
+ To enable the preedit relocation feature, the input context class
+ have to reimplement isPreeditRelocationEnabled() as returns TRUE.
+ The implementation requires that the preedit preservation is also
+ enabled since preedit relocation is a special case of the preedit
+ preservation. If the preedit relocation is disabled, the input
+ context is simply reset in the relocation case.
+
+
+ \section1 Input context instanciation
+ \section1 Input method switching
+
+ \section1 Text widget implementor's guide
+
+ Add following code fragment into createPopupMenu() to add input
+ method dependent submenus.
+
+ \code
+ #ifndef TQT_NO_IM
+ TQInputContext *qic = getInputContext();
+ if ( qic )
+ qic->addMenusTo( popup );
+ #endif
+ \endcode
+
+ \sa TQInputContextPlugin, TQInputContextFactory, TQApplication::locateICHolderWidget(), TQApplication::defaultInputMethod()
+*/
+
+
+/*!
+ Constructs an input context.
+
+ holderWidget is set immediately after this constructor has been
+ returned on the X11 platform.
+*/
+TQInputContext::TQInputContext( TQObject *tqparent )
+ : TQObject( tqparent )
+{
+ d = new TQInputContextPrivate;
+}
+
+
+/*!
+ Destroys the input context.
+*/
+TQInputContext::~TQInputContext()
+{
+ delete d;
+}
+
+#if defined(TQ_WS_X11)
+/*!
+ \internal
+ Returns the owner of this input context. Ordinary input methods
+ should not call this function directly to keep platform
+ independence and flexible configuration possibility.
+
+ The return value may differ from tqfocusWidget() if the input
+ context is shared between several text widgets.
+
+ \sa setHolderWidget(), tqfocusWidget()
+*/
+TQWidget *TQInputContext::holderWidget() const
+{
+ return d->holderWidget;
+}
+
+/*!
+ \internal
+ Sets the owner of this input context. Ordinary input methods
+ must not call this function directly.
+
+ \sa holderWidget()
+*/
+void TQInputContext::setHolderWidget( TQWidget *w )
+{
+ d->holderWidget = w;
+}
+
+/*!
+ \internal
+ Returns the widget that has an input focus for this input
+ context. Ordinary input methods should not call this function
+ directly to keep platform independence and flexible configuration
+ possibility.
+
+ The return value may differ from holderWidget() if the input
+ context is shared between several text widgets.
+
+ \sa setFocusWidget(), holderWidget()
+*/
+TQWidget *TQInputContext::tqfocusWidget() const
+{
+ return d->hasFocus ? d->composingWidget : 0;
+}
+
+
+/*!
+ \internal
+ Sets the widget that has an input focus for this input
+ context. Ordinary input methods must not call this function
+ directly.
+
+ \sa tqfocusWidget()
+*/
+void TQInputContext::setFocusWidget( TQWidget *w )
+{
+ if ( w ) {
+ bool isFocusingBack = ( w == d->composingWidget );
+ bool isPreeditRelocation = ( ! isFocusingBack && isComposing() &&
+ d->composingWidget );
+ // invoke sendIMEventInternal() rather than sendIMEvent() to
+ // avoid altering the composing state
+ if ( isPreeditRelocation == TRUE ) {
+ // clear preedit of previously focused text
+ // widget. preserved preedit may be exist even if
+ // isPreeditRelocationEnabled() == FALSE.
+ sendIMEventInternal( TQEvent::IMEnd );
+ }
+ d->composingWidget = w; // changes recipient of TQIMEvent
+ if ( isPreeditRelocation == TRUE ) {
+#if !defined(TQT_NO_IM_PREEDIT_RELOCATION)
+ if ( isPreeditRelocationEnabled() ) {
+ // copy preedit state to the widget that gaining focus
+ sendIMEventInternal( TQEvent::IMStart );
+ sendIMEventInternal( TQEvent::IMCompose, d->preeditString,
+ d->cursorPosition, d->selLength );
+ } else
+#endif
+ {
+ // reset input context when the shared context has
+ // focused on another text widget
+ reset();
+ }
+ }
+ }
+ d->hasFocus = w ? TRUE : FALSE;
+}
+
+
+/*!
+ \internal
+ This function is called from TQWidget to keep input state
+ consistency. Ordinary input method must not call this function
+ directly.
+*/
+void TQInputContext::releaseComposingWidget( TQWidget *w )
+{
+ if ( d->composingWidget == w ) {
+ d->composingWidget = 0;
+ d->hasFocus = FALSE;
+ }
+}
+#endif // TQ_WS_X11
+
+/*!
+ \internal
+ This function can be reimplemented in a subclass as returning TRUE
+ if you want making your input method enable the preedit
+ relocation. See the description for preedit relocation of
+ TQInputContext.
+
+ /sa TQInputContext
+*/
+bool TQInputContext::isPreeditRelocationEnabled()
+{
+ return FALSE;
+}
+
+/*!
+ This function indicates whether IMStart event had been sent to the
+ text widget. It is ensured that an input context can send IMCompose
+ or IMEnd event safely if this function returned TRUE.
+
+ The state is automatically being tracked through sendIMEvent().
+
+ \sa sendIMEvent()
+*/
+bool TQInputContext::isComposing() const
+{
+ return d->isComposing;
+}
+
+
+/*!
+ This function can be reimplemented in a subclass to filter input
+ events.
+
+ Return TRUE if the \a event has been consumed. Otherwise, the
+ unfiltered \a event will be forwarded to widgets as ordinary
+ way. Although the input events have accept() and ignore()
+ methods, leave it untouched.
+
+ \a event is currently restricted to TQKeyEvent. But some input
+ method related events such as TQWheelEvent or TQTabletEvent may be
+ added in future.
+
+ The filtering opportunity is always given to the input context as
+ soon as possible. 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.
+
+ Ordinary input methods require discrete key events to work
+ properly, so TQt's key compression is always disabled for any input
+ contexts.
+
+ \sa TQKeyEvent, x11FilterEvent()
+*/
+bool TQInputContext::filterEvent( const TQEvent *event )
+{
+ return FALSE;
+}
+
+
+/*!
+ \fn void TQInputContext::deletionRequested()
+
+ Emit this signal when a fatal error has been caused in the input
+ context. The input context will be deleted by the owner which is
+ usually the holder widget.
+*/
+
+/*!
+ \fn void TQInputContext::imEventGenerated( TQObject *receiver, TQIMEvent *e )
+
+ \internal
+ This signal is emitted when the user has sent a TQIMEvent through
+ sendIMEvent(). Ordinary input methods should not emit this signal
+ directly.
+
+ \a receiver is a platform dependent destination of the \a e.
+
+ \sa TQIMEvent, sendIMEvent(), sendIMEventInternal(),
+*/
+
+/*!
+ \internal
+ Sends a TQIMEvent to the client via imEventGenerated()
+ signal. Ordinary input method should not call this function
+ directly.
+
+ \sa TQIMEvent, TQIMComposeEvent, sendIMEvent(), imEventGenerated()
+*/
+void TQInputContext::sendIMEventInternal( TQEvent::Type type,
+ const TQString &text,
+ int cursorPosition, int selLength )
+{
+ TQObject *receiver = 0;
+ TQIMEvent *event = 0;
+
+#if defined(TQ_WS_X11)
+ receiver = d->composingWidget;
+#elif defined(TQ_WS_TQWS)
+ // just a placeholder
+#endif
+ if ( ! receiver )
+ return;
+
+ if ( type == TQEvent::IMStart ) {
+ qDebug( "sending IMStart with %d chars to %p",
+ text.length(), receiver );
+ event = new TQIMEvent( type, text, cursorPosition );
+ } else if ( type == TQEvent::IMEnd ) {
+ qDebug( "sending IMEnd with %d chars to %p, text=%s",
+ text.length(), receiver, (const char*)text.local8Bit() );
+ event = new TQIMEvent( type, text, cursorPosition );
+ } else if ( type == TQEvent::IMCompose ) {
+ qDebug( "sending IMCompose to %p with %d chars, cpos=%d, sellen=%d, text=%s",
+ receiver, text.length(), cursorPosition, selLength,
+ (const char*)text.local8Bit() );
+ event = new TQIMComposeEvent( type, text, cursorPosition, selLength );
+ }
+
+ if ( event )
+ emit imEventGenerated( receiver, event );
+}
+
+
+/*!
+ Call this function to send TQIMEvent to the text widget. This
+ function constructs a TQIMEvent based on the arguments and send it
+ to the appropriate widget. Ordinary input method should not
+ reimplement this function.
+
+ \a type is either \c TQEvent::IMStart or \c TQEvent::IMCompose or \c
+ TQEvent::IMEnd. You have to send a \c TQEvent::IMStart to start
+ composing, then send several \c TQEvent::IMCompose to update the
+ preedit of the widget, and finalize the composition with sending
+ \c TQEvent::IMEnd.
+
+ \c TQEvent::IMStart should always be sent without arguments as:
+ \code
+ sendIMEvent( TQEvent::IMStart )
+ \endcode
+
+ And \c TQEvent::IMCompose can be sent without cursor:
+ \code
+ sendIMEvent( TQEvent::IMCompose, TQString( "a text" ) )
+ \endcode
+
+ Or optionally with cursor with \a cursorPosition:
+ \code
+ sendIMEvent( TQEvent::IMCompose, TQString( "a text with cursor" ), 12 )
+ \endcode
+ Note that \a cursorPosition also specifies microfocus position.
+
+ Or optionally with selection text:
+ \code
+ sendIMEvent( TQEvent::IMCompose, TQString( "a text with selection" ), 12, 9 )
+ \endcode
+ \a cursorPosition and \a selLength must be within the \a text. The
+ \a cursorPosition also specifies microfocus position in the case:
+
+ \c TQEvent::IMEnd can be sent without arguments to terminate the
+ composition with null string:
+ \code
+ sendIMEvent( TQEvent::IMEnd )
+ \endcode
+
+ Or optionally accepts \a text to commit a string:
+ \code
+ sendIMEvent( TQEvent::IMEnd, TQString( "a text" ) )
+ \endcode
+
+ \sa TQIMEvent, TQIMComposeEvent, setMicroFocus()
+*/
+void TQInputContext::sendIMEvent( TQEvent::Type type, const TQString &text,
+ int cursorPosition, int selLength )
+{
+#if defined(TQ_WS_X11)
+ if ( !tqfocusWidget() )
+ return;
+#endif
+
+ if ( type == TQEvent::IMStart ) {
+ sendIMEventInternal( type, text, cursorPosition, selLength );
+ d->isComposing = TRUE;
+ } else if ( type == TQEvent::IMEnd ) {
+ d->resetComposingState();
+ sendIMEventInternal( type, text, cursorPosition, selLength );
+ } else if ( type == TQEvent::IMCompose ) {
+ d->updateComposingState( text, cursorPosition, selLength );
+ sendIMEventInternal( type, text, cursorPosition, selLength );
+ }
+}
+
+
+/*!
+ This function can be reimplemented in a subclass to detect
+ that the input context has been focused on.
+
+ The input context will receive input events through
+ x11FilterEvent() and filterEvent() after setFocus() until
+ unsetFocus() has been called.
+
+ an input context is ensured that setFocus() is called exactly once
+ until unsetFocus() has been called even if preedit relocation has
+ occurred. This means that an input focus will survive between
+ several widgets that sharing the input context.
+
+ On the X11 platform, tqfocusWidget is already set before this
+ function has been called.
+
+ \sa unsetFocus()
+*/
+void TQInputContext::setFocus()
+{
+}
+
+
+/*!
+ This function can be reimplemented in a subclass to detect
+ that the input context has lost the focus.
+
+ an input context is ensured that unsetFocus() is not called during
+ preedit relocation. This means that an input focus will survive
+ between several widgets that sharing the input context.
+
+ Default implementation that calls reset() is sufficient for simple
+ input methods. You can override this function to alter the
+ behavior. For example, most Japanese input contexts should not be
+ reset on losing focus. The context sometimes contains a whole
+ paragraph and has minutes of lifetime different to ephemeral one
+ in other languages. The piled input context should be survived
+ until focused again since Japanese user naturally expects so.
+
+ On the X11 platform, tqfocusWidget is valid until this function has
+ been returned.
+
+ \sa setFocus()
+*/
+void TQInputContext::unsetFocus()
+{
+ reset();
+}
+
+
+/*!
+ This function can be implemented in a subclass to handle
+ microfocus changes.
+
+ 'microfocus' stands for the input method focus point in the
+ preedit (XIM "spot" point) for complex language input handling. It
+ can be used to place auxiliary GUI widgets such as candidate
+ selection window.
+
+ \a x, \a y, \a w and \a h represents the position and size of the
+ cursor in the preedit string. \a f is the font on the location of
+ the cursor.
+*/
+void TQInputContext::setMicroFocus( int x, int y, int w, int h, TQFont *f )
+{
+}
+
+
+/*!
+ This function can be reimplemented in a subclass to handle mouse
+ presses/releases/doubleclicks/moves within the preedit text. You
+ can use the function to implement mouse-oriented user interface
+ such as text selection or popup menu for candidate selection.
+
+ The parameter \a x is the offset within the string that was sent
+ with the IMCompose event. The alteration boundary of \a x is
+ ensured as character boundary of preedit string accurately.
+
+ \a type is either \c TQEvent::MouseButtonPress or \c
+ TQEvent::MouseButtonRelease or \c TQEvent::MouseButtonDblClick or \c
+ TQEvent::MouseButtonMove. Refer \a button and \a state to determine
+ what operation has performed.
+
+ The method interface is imported from
+ TQWSInputMethod::mouseHandler() of TQt/Embedded 2.3.7 and extended
+ for desktop system.
+ */
+void TQInputContext::mouseHandler( int x, TQEvent::Type type,
+ TQt::ButtonState button,
+ TQt::ButtonState state )
+{
+ // Default behavior for simple ephemeral input contexts. Some
+ // complex input contexts should not be reset here.
+ if ( type == TQEvent::MouseButtonPress ||
+ type == TQEvent::MouseButtonDblClick )
+ reset();
+}
+
+
+/*!
+ Returns the font of the current input widget
+ */
+TQFont TQInputContext::font() const
+{
+ if ( !tqfocusWidget() )
+ return TQApplication::font(); //### absolutely last resort
+
+ return tqfocusWidget()->font();
+}
+
+
+/*!
+ This function can be reimplemented in a subclass to reset the
+ state of the input method.
+
+ This function is called by several widgets to reset input
+ state. For example, a text widget call this function before
+ inserting a text to make widget ready to accept a text.
+
+ Default implementation is sufficient for simple input method. You
+ can override this function to reset external input method engines
+ in complex input method. In the case, call TQInputContext::reset()
+ to ensure proper termination of inputting.
+
+ You must not send any TQIMEvent except empty IMEnd event using
+ TQInputContext::reset() at reimplemented reset(). It will break
+ input state consistency.
+*/
+void TQInputContext::reset()
+{
+ if ( isComposing() )
+ sendIMEvent( TQEvent::IMEnd );
+}
+
+
+/*!
+ This function must be implemented in any subclasses to return the
+ identifier name of the input method.
+
+ Return value is the name to identify and specify input methods for
+ the input method switching mechanism and so on. The name has to be
+ consistent with TQInputContextPlugin::keys(). The name has to
+ consist of ASCII characters only.
+
+ There are two different names with different responsibility in the
+ input method domain. This function returns one of them. Another
+ name is called 'display name' that stands for the name for
+ endusers appeared in a menu and so on.
+
+ \sa TQInputContextPlugin::keys(), TQInputContextPlugin::displayName()
+*/
+TQString TQInputContext::identifierName()
+{
+ return "";
+}
+
+
+/*!
+ This function must be implemented in any subclasses to return a
+ language code (e.g. "zh_CN", "zh_TW", "zh_HK", "ja", "ko", ...)
+ of the input context. If the input context can handle multiple
+ languages, return the currently used one. The name has to be
+ consistent with TQInputContextPlugin::language().
+
+ This information will be used by language tagging feature in
+ TQIMEvent. It is required to distinguish unified han characters
+ correctly. It enables proper font and character code
+ handling. Suppose CJK-awared multilingual web browser
+ (that automatically modifies fonts in CJK-mixed text) and XML editor
+ (that automatically inserts lang attr).
+
+ \sa TQInputContextPlugin::language()
+*/
+TQString TQInputContext::language()
+{
+ return "";
+}
+
+
+#if ([[[TQT_VERSION IS DEPRECATED]]]-0 >= 0x040000)
+/*!
+ This is a preliminary interface for TQt4
+ */
+TQList<TQAction *> TQInputContext::actions()
+{
+}
+#else
+/*!
+ This function can be reimplemented in a subclass to provide input
+ method dependent popup menus. Return 0 if the menus are
+ unnecessary.
+
+ Ownership of the object and tqchildren are transferred to the
+ caller, and the result must not be called
+ setAutoDelete(). TQInputContextMenu::title is used for label text
+ of the popup menu as submenu.
+
+ \sa addMenusTo()
+*/
+TQPtrList<TQInputContextMenu> *TQInputContext::menus()
+{
+ return 0;
+}
+#endif
+
+/*!
+ Appends input method dependent submenus into \a popup. A separator
+ is also inserted into \a popup if \a action is InsertSeparator.
+
+ This is an utility function only for convenience in limited
+ situation. This function is used by input context owner such as
+ text widgets to add the submenus to its own context menu. If you
+ want to insert the submenus in more flexible way, use
+ TQInputContext::menus() manually. \a popup is not restricted to
+ context menu of a text widget. For example, the owner may be a
+ input method menu of TQtopia taskbar in TQt/Embedded platform.
+
+ \sa menus(), TQInputContextMenu::Action
+*/
+void TQInputContext::addMenusTo( TQPopupMenu *popup, TQInputContextMenu::Action action )
+{
+ if ( ! popup )
+ return;
+
+ TQPtrList<TQInputContextMenu> *imMenus = menus();
+ if ( imMenus ) {
+ if ( action == TQInputContextMenu::InsertSeparator )
+ popup->insertSeparator();
+ for ( TQPtrList<TQInputContextMenu>::Iterator it = imMenus->begin();
+ it != imMenus->end();
+ ++it ) {
+ TQInputContextMenu *imMenu = *it;
+ popup->insertItem( imMenu->title, imMenu->popup );
+ }
+ imMenus->clear();
+ delete imMenus;
+ }
+}
+
+#endif //TQ_NO_IM
diff --git a/tqtinterface/qt4/src/kernel/tqinputcontext.h b/tqtinterface/qt4/src/kernel/tqinputcontext.h
new file mode 100644
index 0000000..9dbd9bf
--- /dev/null
+++ b/tqtinterface/qt4/src/kernel/tqinputcontext.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+** $Id: qinputcontext.h,v 1.8 2004/06/22 06:47:30 daisuke Exp $
+**
+** Definition of TQInputContext
+**
+** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the kernel module of the TQt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.TQPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid TQt Enterprise Edition or TQt Professional Edition
+** licenses may use this file in accordance with the TQt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about TQt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for TQPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef TQINPUTCONTEXT_H
+#define TQINPUTCONTEXT_H
+
+#ifndef TQT_NO_IM
+
+#ifndef TQT_H
+#include "tqobject.h"
+#include "tqglobal.h"
+#include "tqevent.h"
+#include "tqstring.h"
+#if ([[[TQT_VERSION IS DEPRECATED]]]-0 >= 0x040000)
+#include "tqlist.h"
+#include "tqaction.h"
+#else
+#include "tqptrlist.h"
+#endif
+#endif
+
+class TQWidget;
+class TQFont;
+class TQPopupMenu;
+class TQInputContextPrivate;
+
+
+struct TQInputContextMenu {
+ enum Action {
+ NoSeparator,
+ InsertSeparator
+ };
+#if !([[[TQT_VERSION IS DEPRECATED]]]-0 >= 0x040000)
+ TQString title;
+ TQPopupMenu *popup;
+#endif
+};
+
+
+class TQInputContext : public TQObject
+{
+ TQ_OBJECT
+public:
+ TQInputContext( TQObject *tqparent = 0 );
+ virtual ~TQInputContext();
+
+ virtual TQString identifierName();
+ virtual TQString language();
+
+#if defined(TQ_WS_X11)
+ virtual bool x11FilterEvent( TQWidget *keywidget, XEvent *event );
+#endif // TQ_WS_X11
+ virtual bool filterEvent( const TQEvent *event );
+ virtual void reset();
+
+ virtual void setFocus();
+ virtual void unsetFocus();
+ virtual void setMicroFocus( int x, int y, int w, int h, TQFont *f = 0 );
+ virtual void mouseHandler( int x, TQEvent::Type type,
+ TQt::ButtonState button, TQt::ButtonState state );
+ virtual TQFont font() const;
+ virtual bool isComposing() const;
+ virtual bool isPreeditRelocationEnabled();
+
+#if ([[[TQT_VERSION IS DEPRECATED]]]-0 >= 0x040000)
+ virtual TQList<TQAction *> actions();
+ void addActionsTo( TQMenu *menu, TQInputContextMenu::Action action = TQInputContextMenu::InsertSeparator );
+#else
+ virtual TQPtrList<TQInputContextMenu> *menus();
+ void addMenusTo( TQPopupMenu *popup, TQInputContextMenu::Action action = TQInputContextMenu::InsertSeparator );
+#endif
+
+#if defined(TQ_WS_X11)
+ // these functions are not recommended for ordinary use
+ virtual TQWidget *tqfocusWidget() const;
+ virtual TQWidget *holderWidget() const;
+
+ // these functions must not be used by ordinary input method
+ virtual void setFocusWidget( TQWidget *w );
+ virtual void setHolderWidget( TQWidget *w );
+ virtual void releaseComposingWidget( TQWidget *w );
+#endif
+
+signals:
+ void deletionRequested();
+ void imEventGenerated( TQObject *receiver, TQIMEvent *e );
+
+protected:
+ virtual void sendIMEvent( TQEvent::Type type,
+ const TQString &text = TQString(),
+ int cursorPosition = -1, int selLength = 0 );
+
+private:
+ void sendIMEventInternal( TQEvent::Type type,
+ const TQString &text = TQString(),
+ int cursorPosition = -1, int selLength = 0 );
+
+ TQInputContextPrivate *d;
+
+ friend class TQWidget;
+ friend class TQInputContextFactory;
+
+private: // Disabled copy constructor and operator=
+ TQInputContext( const TQInputContext & );
+ TQInputContext &operator=( const TQInputContext & );
+
+};
+
+#endif //TQ_NO_IM
+
+#endif // TQINPUTCONTEXT_H
diff --git a/tqtinterface/qt4/src/kernel/tqinputcontext_x11.cpp b/tqtinterface/qt4/src/kernel/tqinputcontext_x11.cpp
index 758b56d..e96c75c 100644
--- a/tqtinterface/qt4/src/kernel/tqinputcontext_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqinputcontext_x11.cpp
@@ -36,500 +36,34 @@
**
**********************************************************************/
+#include "tqinputcontext.h"
+
+#ifndef TQT_NO_IM
+
#include "tqplatformdefs.h"
#include "tqapplication.h"
#include "tqwidget.h"
-#include "tqinputcontext_p.h"
-
-#include <stdlib.h>
-#include <limits.h>
+#include "tqt_x11_p.h"
-bool qt_compose_emptied = FALSE;
+/*!
+ This function may be overridden only if input method is depending
+ on X11 and you need raw XEvent. Otherwise, this function must not.
-#if !defined(TQT_NO_XIM)
+ This function is designed to filter raw key events for XIM, but
+ other input methods may use this to implement some special
+ features such as distinguishing Shift_L and Shift_R.
-#define XK_MISCELLANY
-#define XK_LATIN1
-#include <X11/keysymdef.h>
+ Return TRUE if the \a event has been consumed. Otherwise, the
+ unfiltered \a event will be translated into TQEvent and forwarded
+ to filterEvent(). Filtering at both x11FilterEvent() and
+ filterEvent() in single input method is allowed.
-// #define TQT_XIM_DEBUG
+ \a keywidget is a client widget into which a text is inputted. \a
+ event is inputted XEvent.
-// from qapplication_x11.cpp
-extern XIM qt_xim;
-extern XIMStyle qt_xim_style;
-
-/* The cache here is needed, as X11 leaks a few kb for every
- XFreeFontSet call, so we avoid creating and deletion of fontsets as
- much as possible
+ \sa filterEvent()
*/
-static XFontSet fontsetCache[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-static int fontsetRefCount = 0;
-
-static const char * const fontsetnames[] = {
- "-*-fixed-medium-r-*-*-16-*,-*-*-medium-r-*-*-16-*",
- "-*-fixed-medium-i-*-*-16-*,-*-*-medium-i-*-*-16-*",
- "-*-fixed-bold-r-*-*-16-*,-*-*-bold-r-*-*-16-*",
- "-*-fixed-bold-i-*-*-16-*,-*-*-bold-i-*-*-16-*",
- "-*-fixed-medium-r-*-*-24-*,-*-*-medium-r-*-*-24-*",
- "-*-fixed-medium-i-*-*-24-*,-*-*-medium-i-*-*-24-*",
- "-*-fixed-bold-r-*-*-24-*,-*-*-bold-r-*-*-24-*",
- "-*-fixed-bold-i-*-*-24-*,-*-*-bold-i-*-*-24-*"
-};
-
-static XFontSet getFontSet( const TQFont &f )
-{
- int i = 0;
- if (f.italic())
- i |= 1;
- if (f.bold())
- i |= 2;
-
- if ( f.pointSize() > 20 )
- i += 4;
-
- if ( !fontsetCache[i] ) {
- Display* dpy = TQPaintDevice::x11AppDisplay();
- int missCount;
- char** missList;
- fontsetCache[i] = XCreateFontSet(dpy, fontsetnames[i], &missList, &missCount, 0);
- if(missCount > 0)
- XFreeStringList(missList);
- if ( !fontsetCache[i] ) {
- fontsetCache[i] = XCreateFontSet(dpy, "-*-fixed-*-*-*-*-16-*", &missList, &missCount, 0);
- if(missCount > 0)
- XFreeStringList(missList);
- if ( !fontsetCache[i] )
- fontsetCache[i] = (XFontSet)-1;
- }
- }
- return (fontsetCache[i] == (XFontSet)-1) ? 0 : fontsetCache[i];
-}
-
-
-#ifdef TQ_C_CALLBACKS
-extern "C" {
-#endif // TQ_C_CALLBACKS
-
- static int xic_start_callback(XIC, XPointer client_data, XPointer) {
- TQInputContext *qic = (TQInputContext *) client_data;
- if (! qic) {
-#ifdef TQT_XIM_DEBUG
- qDebug("compose start: no qic");
-#endif // TQT_XIM_DEBUG
-
- return 0;
- }
-
- qic->composing = TRUE;
- qic->text = TQString::null;
- qic->tqfocusWidget = 0;
-
- if ( qic->selectedChars.size() < 128 )
- qic->selectedChars.resize( 128 );
- qic->selectedChars.fill( 0 );
-
-#ifdef TQT_XIM_DEBUG
- qDebug("compose start");
-#endif // TQT_XIM_DEBUG
-
- return 0;
- }
-
- static int xic_draw_callback(XIC, XPointer client_data, XPointer call_data) {
- TQInputContext *qic = (TQInputContext *) client_data;
- if (! qic) {
-#ifdef TQT_XIM_DEBUG
- qDebug("compose event: invalid compose event %p", qic);
-#endif // TQT_XIM_DEBUG
-
- return 0;
- }
-
- bool send_imstart = FALSE;
- if (tqApp->tqfocusWidget() != qic->tqfocusWidget && qic->text.isEmpty()) {
- if (qic->tqfocusWidget) {
-#ifdef TQT_XIM_DEBUG
- qDebug( "sending IMEnd (empty) to %p", qic->tqfocusWidget );
-#endif // TQT_XIM_DEBUG
-
- TQIMEvent endevent(TQEvent::IMEnd, TQString::null, -1);
- TQApplication::sendEvent(qic->tqfocusWidget, &endevent);
- }
-
- qic->text = TQString::null;
- qic->tqfocusWidget = tqApp->tqfocusWidget();
- qic->composing = FALSE;
-
- if ( qic->selectedChars.size() < 128 )
- qic->selectedChars.resize( 128 );
- qic->selectedChars.fill( 0 );
-
- if (qic->tqfocusWidget) {
- qic->composing = TRUE;
- send_imstart = TRUE;
- }
- }
-
- if (! qic->composing || ! qic->tqfocusWidget) {
-#ifdef TQT_XIM_DEBUG
- qDebug("compose event: invalid compose event %d %p",
- qic->composing, qic->tqfocusWidget);
-#endif // TQT_XIM_DEBUG
-
- return 0;
- }
-
- if ( send_imstart ) {
-#ifdef TQT_XIM_DEBUG
- qDebug( "sending IMStart to %p", qic->tqfocusWidget );
-#endif // TQT_XIM_DEBUG
-
- qt_compose_emptied = FALSE;
- TQIMEvent startevent(TQEvent::IMStart, TQString::null, -1);
- TQApplication::sendEvent(qic->tqfocusWidget, &startevent);
- }
-
- XIMPreeditDrawCallbackStruct *drawstruct =
- (XIMPreeditDrawCallbackStruct *) call_data;
- XIMText *text = (XIMText *) drawstruct->text;
- int cursor = drawstruct->caret, sellen = 0;
-
- if ( ! drawstruct->caret && ! drawstruct->chg_first &&
- ! drawstruct->chg_length && ! text ) {
- // nothing to do
- return 0;
- }
-
- if (text) {
- char *str = 0;
- if (text->encoding_is_wchar) {
- int l = wcstombs(NULL, text->string.wide_char, text->length);
- if (l != -1) {
- str = new char[l + 1];
- wcstombs(str, text->string.wide_char, l);
- str[l] = 0;
- }
- } else
- str = text->string.multi_byte;
-
- if (! str)
- return 0;
-
- TQString s = TQString::fromLocal8Bit(str);
-
- if (text->encoding_is_wchar)
- delete [] str;
-
- if (drawstruct->chg_length < 0)
- qic->text.tqreplace(drawstruct->chg_first, UINT_MAX, s);
- else
- qic->text.tqreplace(drawstruct->chg_first, drawstruct->chg_length, s);
-
- if ( qic->selectedChars.size() < qic->text.length() ) {
- // expand the selectedChars array if the compose string is longer
- uint from = qic->selectedChars.size();
- qic->selectedChars.resize( qic->text.length() );
- for ( uint x = from; from < qic->selectedChars.size(); ++x )
- qic->selectedChars[x] = 0;
- }
-
- uint x;
- bool *p = qic->selectedChars.data() + drawstruct->chg_first;
- // determine if the changed chars are selected based on text->feedback
- for ( x = 0; x < s.length(); ++x )
- *p++ = ( text->feedback ? ( text->feedback[x] & XIMReverse ) : 0 );
-
- // figure out where the selection starts, and how long it is
- p = qic->selectedChars.data();
- bool started = FALSE;
- for ( x = 0; x < TQMIN(qic->text.length(), qic->selectedChars.size()); ++x ) {
- if ( started ) {
- if ( *p ) ++sellen;
- else break;
- } else {
- if ( *p ) {
- cursor = x;
- started = TRUE;
- sellen = 1;
- }
- }
- ++p;
- }
- } else {
- if (drawstruct->chg_length == 0)
- drawstruct->chg_length = -1;
-
- qic->text.remove(drawstruct->chg_first, drawstruct->chg_length);
- qt_compose_emptied = qic->text.isEmpty();
- if ( qt_compose_emptied ) {
-#ifdef TQT_XIM_DEBUG
- qDebug( "compose emptied" );
-#endif // TQT_XIM_DEBUG
-
- // don't send an empty compose, since we will send an IMEnd with
- // either the correct compose text (or null text if the user has
- // cancelled the compose or deleted all chars).
- return 0;
- }
- }
-
-#ifdef TQT_XIM_DEBUG
- qDebug( "sending IMCompose to %p with %d chars",
- qic->tqfocusWidget, qic->text.length() );
-#endif // TQT_XIM_DEBUG
-
- TQIMComposeEvent event( TQEvent::IMCompose, qic->text, cursor, sellen );
- TQApplication::sendEvent(qic->tqfocusWidget, &event);
- return 0;
- }
-
- static int xic_done_callback(XIC, XPointer client_data, XPointer) {
- TQInputContext *qic = (TQInputContext *) client_data;
- if (! qic)
- return 0;
-
- if (qic->composing && qic->tqfocusWidget) {
-#ifdef TQT_XIM_DEBUG
- qDebug( "sending IMEnd (empty) to %p", qic->tqfocusWidget );
-#endif // TQT_XIM_DEBUG
-
- TQIMEvent event(TQEvent::IMEnd, TQString::null, -1);
- TQApplication::sendEvent(qic->tqfocusWidget, &event);
- }
-
- qic->composing = FALSE;
- qic->tqfocusWidget = 0;
-
- if ( qic->selectedChars.size() < 128 )
- qic->selectedChars.resize( 128 );
- qic->selectedChars.fill( 0 );
-
- return 0;
- }
-
-#ifdef TQ_C_CALLBACKS
-}
-#endif // TQ_C_CALLBACKS
-
-#endif // !TQT_NO_XIM
-
-
-
-TQInputContext::TQInputContext(TQWidget *widget)
- : ic(0), tqfocusWidget(0), composing(FALSE), fontset(0)
-{
-#if !defined(TQT_NO_XIM)
- fontsetRefCount++;
- if (! qt_xim) {
- qWarning("TQInputContext: no input method context available");
- return;
- }
-
- if (! widget->isTopLevel()) {
- qWarning("TQInputContext: cannot create input context for non-toplevel widgets");
- return;
- }
-
- XPoint spot;
- XRectangle rect;
- XVaNestedList preedit_attr = 0;
- XIMCallback startcallback, drawcallback, donecallback;
-
- font = widget->font();
- fontset = getFontSet( font );
-
- if (qt_xim_style & XIMPreeditArea) {
- rect.x = 0;
- rect.y = 0;
- rect.width = widget->width();
- rect.height = widget->height();
-
- preedit_attr = XVaCreateNestedList(0,
- XNArea, &rect,
- XNFontSet, fontset,
- (char *) 0);
- } else if (qt_xim_style & XIMPreeditPosition) {
- spot.x = 1;
- spot.y = 1;
-
- preedit_attr = XVaCreateNestedList(0,
- XNSpotLocation, &spot,
- XNFontSet, fontset,
- (char *) 0);
- } else if (qt_xim_style & XIMPreeditCallbacks) {
- startcallback.client_data = (XPointer) this;
- startcallback.callback = (XIMProc) xic_start_callback;
- drawcallback.client_data = (XPointer) this;
- drawcallback.callback = (XIMProc)xic_draw_callback;
- donecallback.client_data = (XPointer) this;
- donecallback.callback = (XIMProc) xic_done_callback;
-
- preedit_attr = XVaCreateNestedList(0,
- XNPreeditStartCallback, &startcallback,
- XNPreeditDrawCallback, &drawcallback,
- XNPreeditDoneCallback, &donecallback,
- (char *) 0);
- }
-
- if (preedit_attr) {
- ic = XCreateIC(qt_xim,
- XNInputStyle, qt_xim_style,
- XNClientWindow, widget->winId(),
- XNPreeditAttributes, preedit_attr,
- (char *) 0);
- XFree(preedit_attr);
- } else
- ic = XCreateIC(qt_xim,
- XNInputStyle, qt_xim_style,
- XNClientWindow, widget->winId(),
- (char *) 0);
-
- if (! ic)
- qFatal("Failed to create XIM input context!");
-
- // when resetting the input context, preserve the input state
- (void) XSetICValues((XIC) ic, XNResetState, XIMPreserveState, (char *) 0);
-#endif // !TQT_NO_XIM
-}
-
-
-TQInputContext::~TQInputContext()
-{
-
-#if !defined(TQT_NO_XIM)
- if (ic)
- XDestroyIC((XIC) ic);
-
- if ( --fontsetRefCount == 0 ) {
- Display *dpy = TQPaintDevice::x11AppDisplay();
- for ( int i = 0; i < 8; i++ ) {
- if ( fontsetCache[i] && fontsetCache[i] != (XFontSet)-1 ) {
- XFreeFontSet(dpy, fontsetCache[i]);
- fontsetCache[i] = 0;
- }
- }
- }
-
-#endif // !TQT_NO_XIM
-
- ic = 0;
- tqfocusWidget = 0;
- composing = FALSE;
-}
-
-
-void TQInputContext::reset()
-{
-#if !defined(TQT_NO_XIM)
- if (tqfocusWidget && composing && ! text.isNull()) {
-#ifdef TQT_XIM_DEBUG
- qDebug("TQInputContext::reset: composing - sending IMEnd (empty) to %p",
- tqfocusWidget);
-#endif // TQT_XIM_DEBUG
-
- TQIMEvent endevent(TQEvent::IMEnd, TQString::null, -1);
- TQApplication::sendEvent(tqfocusWidget, &endevent);
- tqfocusWidget = 0;
- text = TQString::null;
- if ( selectedChars.size() < 128 )
- selectedChars.resize( 128 );
- selectedChars.fill( 0 );
-
- char *mb = XmbResetIC((XIC) ic);
- if (mb)
- XFree(mb);
- }
-#endif // !TQT_NO_XIM
-}
-
-
-void TQInputContext::setComposePosition(int x, int y)
-{
-#if !defined(TQT_NO_XIM)
- if (qt_xim && ic) {
- XPoint point;
- point.x = x;
- point.y = y;
-
- XVaNestedList preedit_attr =
- XVaCreateNestedList(0,
- XNSpotLocation, &point,
-
- (char *) 0);
- XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0);
- XFree(preedit_attr);
- }
-#endif // !TQT_NO_XIM
-}
-
-
-void TQInputContext::setComposeArea(int x, int y, int w, int h)
-{
-#if !defined(TQT_NO_XIM)
- if (qt_xim && ic) {
- XRectangle rect;
- rect.x = x;
- rect.y = y;
- rect.width = w;
- rect.height = h;
-
- XVaNestedList preedit_attr = XVaCreateNestedList(0,
- XNArea, &rect,
-
- (char *) 0);
- XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0);
- XFree(preedit_attr);
- }
-#endif
-}
-
-
-int TQInputContext::lookupString(XKeyEvent *event, TQCString &chars,
- KeySym *key, Status *status) const
-{
- int count = 0;
-
-#if !defined(TQT_NO_XIM)
- if (qt_xim && ic) {
- count = XmbLookupString((XIC) ic, event, chars.data(),
- chars.size(), key, status);
-
- if ((*status) == XBufferOverflow ) {
- chars.resize(count + 1);
- count = XmbLookupString((XIC) ic, event, chars.data(),
- chars.size(), key, status);
- }
- }
-
-#endif // TQT_NO_XIM
-
- return count;
-}
-
-void TQInputContext::setFocus()
-{
-#if !defined(TQT_NO_XIM)
- if (qt_xim && ic)
- XSetICFocus((XIC) ic);
-#endif // !TQT_NO_XIM
-}
-
-void TQInputContext::setXFontSet(const TQFont &f)
-{
-#if !defined(TQT_NO_XIM)
- if (font == f) return; // nothing to do
- font = f;
-
- XFontSet fs = getFontSet(font);
- if (fontset == fs) return; // nothing to do
- fontset = fs;
- XVaNestedList preedit_attr = XVaCreateNestedList(0, XNFontSet, fontset, (char *) 0);
- XSetICValues((XIC) ic, XNPreeditAttributes, preedit_attr, (char *) 0);
- XFree(preedit_attr);
-#else
- TQ_UNUSED( f );
-#endif
-}
+#endif //TQ_NO_IM \ No newline at end of file
diff --git a/tqtinterface/qt4/src/kernel/tqnamespace.h b/tqtinterface/qt4/src/kernel/tqnamespace.h
index b158936..d3919c9 100644
--- a/tqtinterface/qt4/src/kernel/tqnamespace.h
+++ b/tqtinterface/qt4/src/kernel/tqnamespace.h
@@ -512,7 +512,8 @@ typedef Qt::Orientation Orientation;
#ifdef TQT_NO_COMPAT
enum GUIStyle {
WindowsStyle = 1, // ### TQt 4.0: either remove the obsolete enums or clean up compat vs.
- MotifStyle = 4 // ### TQT_NO_COMPAT by reordering or combination into one enum.
+ MotifStyle = 4, // ### TQT_NO_COMPAT by reordering or combination into one enum.
+ GtkStyle = 6 // Gtk compability mode
};
#else
enum GUIStyle {
@@ -520,7 +521,8 @@ typedef Qt::Orientation Orientation;
WindowsStyle,
Win3Style, // OBSOLETE
PMStyle, // OBSOLETE
- MotifStyle
+ MotifStyle,
+ GtkStyle = 6 // Gtk compability mode
};
#endif
@@ -631,6 +633,87 @@ typedef Qt::Orientation Orientation;
Key_Help = (int)Qt::Key_Help,
Key_Direction_L = (int)Qt::Key_Direction_L,
Key_Direction_R = (int)Qt::Key_Direction_R,
+
+ // International input method support (X keycode - 0xEE00, the
+ // definition follows TQt/Embedded 2.3.7) Only interesting if
+ // you are writing your own input method
+
+ // International & multi-key character composition
+ Key_Multi_key = 0x1120, // Multi-key character compose
+ Key_Codeinput = 0x1137,
+ Key_SingleCandidate = 0x113c,
+ Key_MultipleCandidate = 0x113d,
+ Key_PreviousCandidate = 0x113e,
+
+ // Misc Functions
+ Key_Mode_switch = 0x117e, // Character set switch
+ //Key_script_switch = 0x117e, // Alias for mode_switch
+
+ // Japanese keyboard support
+ Key_Kanji = 0x1121, // Kanji, Kanji convert
+ Key_Muhenkan = 0x1122, // Cancel Conversion
+ //Key_Henkan_Mode = 0x1123, // Start/Stop Conversion
+ Key_Henkan = 0x1123, // Alias for Henkan_Mode
+ Key_Romaji = 0x1124, // to Romaji
+ Key_Hiragana = 0x1125, // to Hiragana
+ Key_Katakana = 0x1126, // to Katakana
+ Key_Hiragana_Katakana = 0x1127, // Hiragana/Katakana toggle
+ Key_Zenkaku = 0x1128, // to Zenkaku
+ Key_Hankaku = 0x1129, // to Hankaku
+ Key_Zenkaku_Hankaku = 0x112a, // Zenkaku/Hankaku toggle
+ Key_Touroku = 0x112b, // Add to Dictionary
+ Key_Massyo = 0x112c, // Delete from Dictionary
+ Key_Kana_Lock = 0x112d, // Kana Lock
+ Key_Kana_Shift = 0x112e, // Kana Shift
+ Key_Eisu_Shift = 0x112f, // Alphanumeric Shift
+ Key_Eisu_toggle = 0x1130, // Alphanumeric toggle
+ //Key_Kanji_Bangou = 0x1137, // Codeinput
+ //Key_Zen_Koho = 0x113d, // Multiple/All Candidate(s)
+ //Key_Mae_Koho = 0x113e, // Previous Candidate
+
+ // Korean keyboard support
+ //
+ // In fact, many Korean users need only 2 keys, Key_Hangul and
+ // Key_Hangul_Hanja. But rest of the keys are good for future.
+
+ Key_Hangul = 0x1131, // Hangul start/stop(toggle)
+ Key_Hangul_Start = 0x1132, // Hangul start
+ Key_Hangul_End = 0x1133, // Hangul end, English start
+ Key_Hangul_Hanja = 0x1134, // Start Hangul->Hanja Conversion
+ Key_Hangul_Jamo = 0x1135, // Hangul Jamo mode
+ Key_Hangul_Romaja = 0x1136, // Hangul Romaja mode
+ //Key_Hangul_Codeinput = 0x1137, // Hangul code input mode
+ Key_Hangul_Jeonja = 0x1138, // Jeonja mode
+ Key_Hangul_Banja = 0x1139, // Banja mode
+ Key_Hangul_PreHanja = 0x113a, // Pre Hanja conversion
+ Key_Hangul_PostHanja = 0x113b, // Post Hanja conversion
+ //Key_Hangul_SingleCandidate = 0x113c, // Single candidate
+ //Key_Hangul_MultipleCandidate = 0x113d, // Multiple candidate
+ //Key_Hangul_PreviousCandidate = 0x113e, // Previous candidate
+ Key_Hangul_Special = 0x113f, // Special symbols
+ //Key_Hangul_switch = 0x117e, // Alias for mode_switch
+
+ // dead keys (X keycode - 0xED00 to avoid the conflict)
+ Key_Dead_Grave = 0x1250,
+ Key_Dead_Acute = 0x1251,
+ Key_Dead_Circumflex = 0x1252,
+ Key_Dead_Tilde = 0x1253,
+ Key_Dead_Macron = 0x1254,
+ Key_Dead_Breve = 0x1255,
+ Key_Dead_Abovedot = 0x1256,
+ Key_Dead_Diaeresis = 0x1257,
+ Key_Dead_Abovering = 0x1258,
+ Key_Dead_Doubleacute = 0x1259,
+ Key_Dead_Caron = 0x125a,
+ Key_Dead_Cedilla = 0x125b,
+ Key_Dead_Ogonek = 0x125c,
+ Key_Dead_Iota = 0x125d,
+ Key_Dead_Voiced_Sound = 0x125e,
+ Key_Dead_Semivoiced_Sound = 0x125f,
+ Key_Dead_Belowdot = 0x1260,
+ Key_Dead_Hook = 0x1261,
+ Key_Dead_Horn = 0x1262,
+
Key_Space = (int)Qt::Key_Space, // 7 bit printable ASCII
Key_Any = Key_Space,
Key_Exclam = (int)Qt::Key_Exclam,
@@ -703,6 +786,11 @@ typedef Qt::Orientation Orientation;
Key_AsciiTilde = (int)Qt::Key_AsciiTilde,
// Latin 1 codes adapted from X: keysymdef.h,v 1.21 94/08/28 16:17:06
+ //
+ // This is mainly for compatibility - applications and input
+ // methods should not use the TQt keycodes between 128 and 255,
+ // but should rather use the TQKeyEvent::text(). See
+ // TQETWidget::translateKeyEventInternal() for more details.
Key_nobreakspace = (int)Qt::Key_nobreakspace,
Key_exclamdown = (int)Qt::Key_exclamdown,
diff --git a/tqtinterface/qt4/src/kernel/tqpaintdevice_x11.cpp b/tqtinterface/qt4/src/kernel/tqpaintdevice_x11.cpp
index 2432607..fd4cc0b 100644
--- a/tqtinterface/qt4/src/kernel/tqpaintdevice_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqpaintdevice_x11.cpp
@@ -1105,11 +1105,16 @@ static void create_dpis()
TQ_CHECK_PTR( dpisX );
TQ_CHECK_PTR( dpisY );
for ( i = 0; i < screens; i++ ) {
- dpisX[ i ] = (DisplayWidth(dpy,i) * 254 + DisplayWidthMM(dpy,i)*5)
-
- / (DisplayWidthMM(dpy,i)*10);
- dpisY[ i ] = (DisplayHeight(dpy,i) * 254 + DisplayHeightMM(dpy,i)*5)
- / (DisplayHeightMM(dpy,i)*10);
+ if (DisplayWidthMM(dpy,i) < 1)
+ dpisX[ i ] = 75; // default the dpi to 75.
+ else
+ dpisX[ i ] = (DisplayWidth(dpy,i) * 254 + DisplayWidthMM(dpy,i)*5)
+ / (DisplayWidthMM(dpy,i)*10);
+ if (DisplayHeightMM(dpy,i) < 1)
+ dpisY[ i ] = 75; // default the dpi to 75.
+ else
+ dpisY[ i ] = (DisplayHeight(dpy,i) * 254 + DisplayHeightMM(dpy,i)*5)
+ / (DisplayHeightMM(dpy,i)*10);
}
}
diff --git a/tqtinterface/qt4/src/kernel/tqpixmap_x11.cpp b/tqtinterface/qt4/src/kernel/tqpixmap_x11.cpp
index 974f23c..2a497e5 100644
--- a/tqtinterface/qt4/src/kernel/tqpixmap_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqpixmap_x11.cpp
@@ -40,7 +40,19 @@
// NOT REVISED
+#include "tqplatformdefs.h"
+
+#if defined(Q_OS_WIN32) && defined(TQT_MITSHM)
+#undef TQT_MITSHM
+#endif
+
+#ifdef TQT_MITSHM
+
+// Use the MIT Shared Memory extension for pixmap<->image conversions
+#define TQT_MITSHM_CONVERSIONS
+
// Uncomment the next line to enable the MIT Shared Memory extension
+// for TQPixmap::xForm()
//
// WARNING: This has some problems:
//
@@ -48,7 +60,7 @@
// 2. TQt does not handle the ShmCompletion message, so you will
// get strange effects if you xForm() repeatedly.
//
-// #define TQT_MITSHM
+// #define TQT_MITSHM_XFORM
#if defined(TQ_OS_WIN32) && defined(TQT_MITSHM)
#undef TQT_MITSHM
@@ -131,7 +143,7 @@ inline static void qSafeXDestroyImage( XImage *x )
MIT Shared Memory Extension support: makes xForm noticeably (~20%) faster.
*****************************************************************************/
-#if defined(TQT_MITSHM)
+#if defined(TQT_MITSHM_XFORM)
static bool xshminit = FALSE;
static XShmSegmentInfo xshminfo;
@@ -213,8 +225,100 @@ static bool qt_create_mitshm_buffer( const TQPaintDevice* dev, int w, int h )
// return FALSE;
// }
-#endif // TQT_MITSHM
+#endif // TQT_MITSHM_XFORM
+
+#ifdef TQT_MITSHM_CONVERSIONS
+
+static bool qt_mitshm_error = false;
+static int qt_mitshm_errorhandler( Display*, XErrorEvent* )
+{
+ qt_mitshm_error = true;
+ return 0;
+}
+
+static XImage* qt_XShmCreateImage( Display* dpy, Visual* visual, unsigned int depth,
+ int format, int /*offset*/, char* /*data*/, unsigned int width, unsigned int height,
+ int /*bitmap_pad*/, int /*bytes_per_line*/, XShmSegmentInfo* shminfo )
+{
+ if( width * height * depth < 100*100*32 )
+ return NULL;
+ static int shm_inited = -1;
+ if( shm_inited == -1 ) {
+ if( XShmQueryExtension( dpy ))
+ shm_inited = 1;
+ else
+ shm_inited = 0;
+ }
+ if( shm_inited == 0 )
+ return NULL;
+ XImage* xi = XShmCreateImage( dpy, visual, depth, format, NULL, shminfo, width,
+ height );
+ if( xi == NULL )
+ return NULL;
+ shminfo->shmid = shmget( IPC_PRIVATE, xi->bytes_per_line * xi->height,
+ IPC_CREAT|0600);
+ if( shminfo->shmid < 0 ) {
+ XDestroyImage( xi );
+ return NULL;
+ }
+ shminfo->readOnly = False;
+ shminfo->shmaddr = (char*)shmat( shminfo->shmid, 0, 0 );
+ if( shminfo->shmaddr == (char*)-1 ) {
+ XDestroyImage( xi );
+ shmctl( shminfo->shmid, IPC_RMID, 0 );
+ return NULL;
+ }
+ xi->data = shminfo->shmaddr;
+#ifndef TQT_MITSHM_RMID_IGNORES_REFCOUNT
+ // mark as deleted to automatically free the memory in case
+ // of a crash (but this doesn't work e.g. on Solaris)
+ shmctl( shminfo->shmid, IPC_RMID, 0 );
+#endif
+ if( shm_inited == 1 ) { // first time
+ XErrorHandler old_h = XSetErrorHandler( qt_mitshm_errorhandler );
+ XShmAttach( dpy, shminfo );
+ shm_inited = 2;
+ XSync( dpy, False );
+ XSetErrorHandler( old_h );
+ if( qt_mitshm_error ) { // oops ... perhaps we are remote?
+ shm_inited = 0;
+ XDestroyImage( xi );
+ shmdt( shminfo->shmaddr );
+#ifdef TQT_MITSHM_RMID_IGNORES_REFCOUNT
+ shmctl( shminfo->shmid, IPC_RMID, 0 );
+#endif
+ return NULL;
+ }
+ } else
+ XShmAttach( dpy, shminfo );
+ return xi;
+}
+
+static void qt_XShmDestroyImage( XImage* xi, XShmSegmentInfo* shminfo )
+{
+ XShmDetach( TQPaintDevice::x11AppDisplay(), shminfo );
+ XDestroyImage( xi );
+ shmdt( shminfo->shmaddr );
+#ifdef TQT_MITSHM_RMID_IGNORES_REFCOUNT
+ shmctl( shminfo->shmid, IPC_RMID, 0 );
+#endif
+}
+static XImage* qt_XShmGetImage( const TQPixmap* pix, int format,
+ XShmSegmentInfo* shminfo )
+{
+ XImage* xi = qt_XShmCreateImage( pix->x11Display(), (Visual*)pix->x11Visual(),
+ pix->depth(), format, 0, 0, pix->width(), pix->height(), 32, 0, shminfo );
+ if( xi == NULL )
+ return NULL;
+ if( XShmGetImage( pix->x11Display(), pix->handle(), xi, 0, 0, AllPlanes ) == False ) {
+ qt_XShmDestroyImage( xi, shminfo );
+ return NULL;
+ }
+ return xi;
+}
+
+#endif // TQT_MITSHM_CONVERSIONS
/*****************************************************************************
Internal functions
@@ -667,9 +771,20 @@ TQImage TQPixmap::convertToImage() const
d = 32; // > 8 ==> 32
XImage *xi = (XImage *)data->ximage; // any cached ximage?
- if ( !xi ) // fetch data from X server
+#ifdef TQT_MITSHM_CONVERSIONS
+ bool mitshm_ximage = false;
+ XShmSegmentInfo shminfo;
+#endif
+ if ( !xi ) { // fetch data from X server
+#ifdef TQT_MITSHM_CONVERSIONS
+ xi = qt_XShmGetImage( this, mono ? XYPixmap : ZPixmap, &shminfo );
+ if( xi ) {
+ mitshm_ximage = true;
+ } else
+#endif
xi = XGetImage( x11Display(), hd, 0, 0, w, h, AllPlanes,
mono ? XYPixmap : ZPixmap );
+ }
TQ_CHECK_PTR( xi );
if (!xi)
return image; // null image
@@ -680,15 +795,31 @@ TQImage TQPixmap::convertToImage() const
TQImage::LittleEndian : TQImage::BigEndian;
}
image.create( w, h, d, 0, bitOrder );
- if ( image.isNull() ) // could not create image
+ if ( image.isNull() ) { // could not create image
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_ximage )
+ qt_XShmDestroyImage( xi, &shminfo );
+ else
+#endif
+ qSafeXDestroyImage( xi );
return image;
+ }
const TQPixmap* msk = tqmask();
const TQPixmap *alf = data->alphapm;
TQImage alpha;
if (alf) {
- XImage *axi = XGetImage(x11Display(), alf->hd, 0, 0, w, h, AllPlanes, ZPixmap);
+ XImage* axi;
+#ifdef TQT_MITSHM_CONVERSIONS
+ bool mitshm_aximage = false;
+ XShmSegmentInfo ashminfo;
+ axi = qt_XShmGetImage( alf, ZPixmap, &ashminfo );
+ if( axi ) {
+ mitshm_aximage = true;
+ } else
+#endif
+ axi = XGetImage(x11Display(), alf->hd, 0, 0, w, h, AllPlanes, ZPixmap);
if (axi) {
image.setAlphaBuffer( TRUE );
@@ -702,6 +833,11 @@ TQImage TQPixmap::convertToImage() const
src += axi->bytes_per_line;
}
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_aximage )
+ qt_XShmDestroyImage( axi, &ashminfo );
+ else
+#endif
qSafeXDestroyImage( axi );
}
} else if (msk) {
@@ -844,6 +980,12 @@ TQImage TQPixmap::convertToImage() const
xi->bits_per_pixel );
#endif
image.reset();
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_ximage )
+ qt_XShmDestroyImage( xi, &shminfo );
+ else
+#endif
+ qSafeXDestroyImage( xi );
return image;
}
@@ -949,10 +1091,22 @@ TQImage TQPixmap::convertToImage() const
delete [] carr;
}
if ( data->optim != BestOptim ) { // throw away image data
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_ximage )
+ qt_XShmDestroyImage( xi, &shminfo );
+ else
+#endif
qSafeXDestroyImage( xi );
((TQPixmap*)this)->data->ximage = 0;
- } else // keep ximage data
+ } else { // keep ximage data
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_ximage ) { // copy the XImage?
+ qt_XShmDestroyImage( xi, &shminfo );
+ xi = 0;
+ }
+#endif
((TQPixmap*)this)->data->ximage = xi;
+ }
return image;
}
@@ -1125,6 +1279,11 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
bool trucol = (visual->c_class == TrueColor || visual->c_class == DirectColor);
int nbytes = image.numBytes();
uchar *newbits= 0;
+ int newbits_size = 0;
+#ifdef TQT_MITSHM_CONVERSIONS
+ bool mitshm_ximage = false;
+ XShmSegmentInfo shminfo;
+#endif
if ( trucol ) { // truecolor display
TQRgb pix[256]; // pixel translation table
@@ -1153,19 +1312,24 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
}
}
+#ifdef TQT_MITSHM_CONVERSIONS
+ xi = qt_XShmCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0, &shminfo );
+ if( xi != NULL ) {
+ mitshm_ximage = true;
+ newbits = (uchar*)xi->data;
+ }
+ else
+#endif
xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 );
- TQ_CHECK_PTR( xi );
if (!xi)
return false;
+ if( newbits == NULL )
newbits = (uchar *)malloc( xi->bytes_per_line*h );
TQ_CHECK_PTR( newbits );
if ( !newbits ) // no memory
return FALSE;
int bppc = xi->bits_per_pixel;
- if ( bppc > 8 && xi->byte_order == LSBFirst )
- bppc++;
-
bool contig_bits = n_bits(red_mask) == rbits &&
n_bits(green_mask) == gbits &&
n_bits(blue_mask) == bbits;
@@ -1215,31 +1379,70 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
init=TRUE;
}
- for ( uint y=0; y<h; y++ ) {
- uchar* src = image.scanLine( y );
- uchar* dst = newbits + xi->bytes_per_line*y;
- TQRgb* p = (TQRgb *)src;
+ enum { BPP8,
+ BPP16_8_3_M3, BPP16_7_2_M3, BPP16_MSB, BPP16_LSB,
+ BPP24_MSB, BPP24_LSB,
+ BPP32_16_8_0, BPP32_MSB, BPP32_LSB
+ } mode = BPP8;
-#define GET_RGB \
- int r = tqRed ( *p ); \
- int g = tqGreen( *p ); \
- int b = tqBlue ( *p++ ); \
- r = red_shift > 0 \
- ? r << red_shift : r >> -red_shift; \
- g = green_shift > 0 \
- ? g << green_shift : g >> -green_shift; \
- b = blue_shift > 0 \
- ? b << blue_shift : b >> -blue_shift;
+ if ( bppc > 8 && xi->byte_order == LSBFirst )
+ bppc++;
+
+ int wordsize;
+ bool bigendian;
+ qSysInfo( &wordsize, &bigendian );
+ bool same_msb_lsb = ( xi->byte_order == MSBFirst ) == ( bigendian );
+
+ if( bppc == 8 ) // 8 bit
+ mode = BPP8;
+ else if( bppc == 16 || bppc == 17 ) { // 16 bit MSB/LSB
+ if( red_shift == 8 && green_shift == 3 && blue_shift == -3
+ && !d8 && same_msb_lsb )
+ mode = BPP16_8_3_M3;
+ else if( red_shift == 7 && green_shift == 2 && blue_shift == -3
+ && !d8 && same_msb_lsb )
+ mode = BPP16_7_2_M3;
+ else
+ mode = bppc == 17 ? BPP16_LSB : BPP16_MSB;
+ } else if( bppc == 24 || bppc == 25 ) { // 24 bit MSB/LSB
+ mode = bppc == 25 ? BPP24_LSB : BPP24_MSB;
+ } else if( bppc == 32 || bppc == 33 ) { // 32 bit MSB/LSB
+ if( red_shift == 16 && green_shift == 8 && blue_shift == 0
+ && !d8 && same_msb_lsb )
+ mode = BPP32_16_8_0;
+ else
+ mode = bppc == 33 ? BPP32_LSB : BPP32_MSB;
+ } else
+ qFatal("Logic error 3");
#define GET_PIXEL \
int pixel; \
if ( d8 ) pixel = pix[*src++]; \
else { \
- GET_RGB \
- pixel = (b & blue_mask)|(g & green_mask) | (r & red_mask) \
+ int r = tqRed ( *p ); \
+ int g = tqGreen( *p ); \
+ int b = tqBlue ( *p++ ); \
+ r = red_shift > 0 \
+ ? r << red_shift : r >> -red_shift; \
+ g = green_shift > 0 \
+ ? g << green_shift : g >> -green_shift; \
+ b = blue_shift > 0 \
+ ? b << blue_shift : b >> -blue_shift; \
+ pixel = (r & red_tqmask)|(g & green_tqmask) | (b & blue_tqmask) \
| ~(blue_mask | green_mask | red_mask); \
}
+// optimized case - no d8 case, shift only once instead of twice, tqmask only once instead of twice,
+// use direct values instead of variables, and use only one statement
+// (*p >> 16), (*p >> 8 ) and (*p) are tqRed(),tqGreen() and tqBlue() without masking
+// shifts have to be passed including the shift operator (e.g. '>>3'), because of the direction
+#define GET_PIXEL_OPT(red_shift,green_shift,blue_shift,red_tqmask,green_tqmask,blue_tqmask) \
+ int pixel = ((( *p >> 16 ) red_shift ) & red_tqmask ) \
+ | ((( *p >> 8 ) green_shift ) & green_tqmask ) \
+ | ((( *p ) blue_shift ) & blue_tqmask ); \
+ ++p;
+
+
#define GET_PIXEL_DITHER_TC \
int r = tqRed ( *p ); \
int g = tqGreen( *p ); \
@@ -1262,89 +1465,176 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
? b << blue_shift : b >> -blue_shift; \
int pixel = (b & blue_mask)|(g & green_mask) | (r & red_mask);
- if ( dither_tc ) {
- uint x;
- switch ( bppc ) {
- case 16: // 16 bit MSB
- for ( x=0; x<w; x++ ) {
- GET_PIXEL_DITHER_TC
- *dst++ = (pixel >> 8);
- *dst++ = pixel;
- }
+// again, optimized case
+// can't be optimized that much :(
+#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_tqmask,green_tqmask,blue_tqmask, \
+ rbits,gbits,bbits) \
+ const int thres = D[x%16][y%16]; \
+ int r = tqRed ( *p ); \
+ if ( r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
+ > thres) \
+ r += (1<<(8-rbits)); \
+ int g = tqGreen( *p ); \
+ if ( g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
+ > thres) \
+ g += (1<<(8-gbits)); \
+ int b = tqBlue ( *p++ ); \
+ if ( b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
+ > thres) \
+ b += (1<<(8-bbits)); \
+ int pixel = (( r red_shift ) & red_tqmask ) \
+ | (( g green_shift ) & green_tqmask ) \
+ | (( b blue_shift ) & blue_tqmask );
+
+#define CYCLE(body) \
+ for ( uint y=0; y<h; y++ ) { \
+ uchar* src = image.scanLine( y ); \
+ uchar* dst = newbits + xi->bytes_per_line*y; \
+ TQRgb* p = (TQRgb *)src; \
+ body \
+ }
+
+ if ( dither_tc ) {
+ switch ( mode ) {
+ case BPP16_8_3_M3:
+ CYCLE(
+ TQ_INT16* dst16 = (TQ_INT16*)dst;
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL_DITHER_TC_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f,5,6,5)
+ *dst16++ = pixel;
+ }
+ )
break;
- case 17: // 16 bit LSB
- for ( x=0; x<w; x++ ) {
- GET_PIXEL_DITHER_TC
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- }
+ case BPP16_7_2_M3:
+ CYCLE(
+ TQ_INT16* dst16 = (TQ_INT16*)dst;
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f)
+ *dst16++ = pixel;
+ }
+ )
break;
default:
qFatal("Logic error");
}
- } else {
- uint x;
- switch ( bppc ) {
- case 8: // 8 bit
- for ( x=0; x<w; x++ ) {
- int pixel = pix[*src++];
- *dst++ = pixel;
- }
+ } else {
+ switch ( mode ) {
+ case BPP8: // 8 bit
+ CYCLE(
+ Q_UNUSED(p);
+ for ( uint x=0; x<w; x++ ) {
+ int pixel = pix[*src++];
+ *dst++ = pixel;
+ }
+ )
break;
- case 16: // 16 bit MSB
- for ( x=0; x<w; x++ ) {
- GET_PIXEL
- *dst++ = (pixel >> 8);
- *dst++ = pixel;
- }
+ case BPP16_8_3_M3:
+ CYCLE(
+ TQ_INT16* dst16 = (TQ_INT16*)dst;
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f)
+ *dst16++ = pixel;
+ }
+ )
break;
- case 17: // 16 bit LSB
- for ( x=0; x<w; x++ ) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- }
+ case BPP16_7_2_M3:
+ CYCLE(
+ TQ_INT16* dst16 = (TQ_INT16*)dst;
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL_DITHER_TC_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f,5,5,5)
+ *dst16++ = pixel;
+ }
+ )
break;
- case 24: // 24 bit MSB
- for ( x=0; x<w; x++ ) {
- GET_PIXEL
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 8;
- *dst++ = pixel;
- }
+ case BPP16_MSB: // 16 bit MSB
+ CYCLE(
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL_DITHER_TC
+ *dst++ = (pixel >> 8);
+ *dst++ = pixel;
+ }
+ )
break;
- case 25: // 24 bit LSB
- for ( x=0; x<w; x++ ) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- *dst++ = pixel >> 16;
- }
+ case BPP16_LSB: // 16 bit LSB
+ CYCLE(
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL_DITHER_TC
+ *dst++ = pixel;
+ *dst++ = pixel >> 8;
+ }
+ )
break;
- case 32: // 32 bit MSB
- for ( x=0; x<w; x++ ) {
- GET_PIXEL
- *dst++ = pixel >> 24;
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 8;
- *dst++ = pixel;
- }
+ case BPP16_MSB: // 16 bit MSB
+ CYCLE(
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL
+ *dst++ = (pixel >> 8);
+ *dst++ = pixel;
+ }
+ )
+ break;
+ case BPP16_LSB: // 16 bit LSB
+ CYCLE(
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL
+ *dst++ = pixel;
+ *dst++ = pixel >> 8;
+ }
+ )
+ break;
+ case BPP24_MSB: // 24 bit MSB
+ CYCLE(
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL
+ *dst++ = pixel >> 16;
+ *dst++ = pixel >> 8;
+ *dst++ = pixel;
+ }
+ )
break;
case 33: // 32 bit LSB
- for ( x=0; x<w; x++ ) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 24;
- }
+ case BPP24_LSB: // 24 bit LSB
+ CYCLE(
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL
+ *dst++ = pixel;
+ *dst++ = pixel >> 8;
+ *dst++ = pixel >> 16;
+ }
+ )
break;
- default:
- qFatal("Logic error 2");
- }
- }
- }
- xi->data = (char *)newbits;
+ case BPP32_16_8_0:
+ CYCLE(
+ memcpy( dst, p, w * 4 );
+ )
+ break;
+ case BPP32_MSB: // 32 bit MSB
+ CYCLE(
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL
+ *dst++ = pixel >> 24;
+ *dst++ = pixel >> 16;
+ *dst++ = pixel >> 8;
+ *dst++ = pixel;
+ }
+ )
+ break;
+ case BPP32_LSB: // 32 bit LSB
+ CYCLE(
+ for ( uint x=0; x<w; x++ ) {
+ GET_PIXEL
+ *dst++ = pixel;
+ *dst++ = pixel >> 8;
+ *dst++ = pixel >> 16;
+ *dst++ = pixel >> 24;
+ }
+ )
+ break;
+ default:
+ qFatal("Logic error 2");
+ }
+ }
+ xi->data = (char *)newbits;
}
if ( d == 8 && !trucol ) { // 8 bit pixmap
@@ -1363,6 +1653,7 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
}
newbits = (uchar *)malloc( nbytes ); // copy image into newbits
+ newbits_size = nbytes;
TQ_CHECK_PTR( newbits );
if ( !newbits ) // no memory
return FALSE;
@@ -1479,12 +1770,19 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
}
}
- if ( !xi ) { // X image not created
+ if ( !xi ) {
+#ifdef TQT_MITSHM_CONVERSIONS
+ xi = qt_XShmCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0, &shminfo );
+ if( xi != NULL )
+ mitshm_ximage = true;
+ else
+#endif // X image not created
xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 );
if ( xi->bits_per_pixel == 16 ) { // convert 8 bpp ==> 16 bpp
ushort *p2;
int p2inc = xi->bytes_per_line/sizeof(ushort);
ushort *newerbits = (ushort *)malloc( xi->bytes_per_line * h );
+ newbits_size = xi->bytes_per_line * h;
TQ_CHECK_PTR( newerbits );
if ( !newerbits ) // no memory
return FALSE;
@@ -1502,6 +1800,14 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
"(bpp=%d)", xi->bits_per_pixel );
#endif
}
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( newbits_size > 0 && mitshm_ximage ) { // need to copy to shared memory
+ memcpy( xi->data, newbits, newbits_size );
+ free( newbits );
+ newbits = (uchar*)xi->data;
+ }
+ else
+#endif
xi->data = (char *)newbits;
}
@@ -1535,19 +1841,24 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
}
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_ximage )
+ XShmPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), FALSE ),
+ xi, 0, 0, 0, 0, w, h, False );
+ else
+#endif
XPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), FALSE ),
xi, 0, 0, 0, 0, w, h );
- if ( data->optim != BestOptim ) { // throw away image
- qSafeXDestroyImage( xi );
- data->ximage = 0;
- } else { // keep ximage that we created
- data->ximage = xi;
- }
data->w = w;
data->h = h;
data->d = dd;
+ XImage* axi = NULL;
+#ifdef TQT_MITSHM_CONVERSIONS
+ bool mitshm_aximage = false;
+ XShmSegmentInfo ashminfo;
+#endif
if ( image.hasAlphaBuffer() ) {
TQBitmap m;
m = image.createAlphaMask( conversion_flags );
@@ -1583,38 +1894,90 @@ bool TQPixmap::convertFromImage( const TQImage &img, int conversion_flags )
data->alphapm->rendhd =
(HANDLE) XftDrawCreateAlpha( x11Display(), data->alphapm->hd, 8 );
- XImage *axi = XCreateImage(x11Display(), (Visual *) x11Visual(),
+#ifdef TQT_MITSHM_CONVERSIONS
+ axi = qt_XShmCreateImage( x11Display(), (Visual*)x11Visual(),
+ 8, ZPixmap, 0, 0, w, h, 8, 0, &ashminfo );
+ if( axi != NULL )
+ mitshm_aximage = true;
+ else
+#endif
+ axi = XCreateImage(x11Display(), (Visual *) x11Visual(),
8, ZPixmap, 0, 0, w, h, 8, 0);
if (axi) {
+ if( axi->data==NULL ) {
// the data is deleted by qSafeXDestroyImage
axi->data = (char *) malloc(h * axi->bytes_per_line);
TQ_CHECK_PTR( axi->data );
+ }
char *aptr = axi->data;
if (image.depth() == 32) {
const int *iptr = (const int *) image.bits();
- int max = w * h;
- while (max--)
- *aptr++ = *iptr++ >> 24; // squirt
+ if( axi->bytes_per_line == (int)w ) {
+ int max = w * h;
+ while (max--)
+ *aptr++ = *iptr++ >> 24; // squirt
+ } else {
+ for (uint i = 0; i < h; ++i ) {
+ for (uint j = 0; j < w; ++j )
+ *aptr++ = *iptr++ >> 24; // squirt
+ aptr += ( axi->bytes_per_line - w );
+ }
+ }
} else if (image.depth() == 8) {
const TQRgb * const rgb = image.colorTable();
for (uint y = 0; y < h; ++y) {
const uchar *iptr = image.scanLine(y);
for (uint x = 0; x < w; ++x)
*aptr++ = tqAlpha(rgb[*iptr++]);
+ aptr += ( axi->bytes_per_line - w );
}
}
GC gc = XCreateGC(x11Display(), data->alphapm->hd, 0, 0);
+ #ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_aximage )
+ XShmPutImage( dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h, False );
+ else
+#endif
XPutImage(dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h);
XFreeGC(x11Display(), gc);
- qSafeXDestroyImage(axi);
}
}
#endif // TQT_NO_XFTFREETYPE
}
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_ximage || mitshm_aximage )
+ XSync( x11Display(), False ); // wait until processed
+#endif
+
+ if ( data->optim != BestOptim ) { // throw away image
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_ximage )
+ qt_XShmDestroyImage( xi, &shminfo );
+ else
+#endif
+ qSafeXDestroyImage( xi );
+ data->ximage = 0;
+ } else { // keep ximage that we created
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_ximage ) { // copy the XImage?
+ qt_XShmDestroyImage( xi, &shminfo );
+ xi = 0;
+ }
+#endif
+ data->ximage = xi;
+ }
+ if( axi ) {
+#ifdef TQT_MITSHM_CONVERSIONS
+ if( mitshm_aximage )
+ qt_XShmDestroyImage( axi, &ashminfo );
+ else
+#endif
+ qSafeXDestroyImage(axi);
+ }
return TRUE;
}
@@ -1777,7 +2140,7 @@ TQPixmap TQPixmap::xForm( const TQWMatrix &matrix ) const
return pm;
}
-#if defined(TQT_MITSHM)
+#if defined(TQT_MITSHM_XFORM)
static bool try_once = TRUE;
if (try_once) {
try_once = FALSE;
@@ -1810,7 +2173,7 @@ TQPixmap TQPixmap::xForm( const TQWMatrix &matrix ) const
dbpl = ((w*bpp+31)/32)*4;
dbytes = dbpl*h;
-#if defined(TQT_MITSHM)
+#if defined(TQT_MITSHM_XFORM)
if ( use_mitshm ) {
dptr = (uchar *)xshmimg->data;
uchar fillbyte = bpp == 8 ? white.pixel() : 0xff;
@@ -1826,7 +2189,7 @@ TQPixmap TQPixmap::xForm( const TQWMatrix &matrix ) const
memset( dptr, TQt::white.pixel( x11Screen() ), dbytes );
else
memset( dptr, 0xff, dbytes );
-#if defined(TQT_MITSHM)
+#if defined(TQT_MITSHM_XFORM)
}
#endif
@@ -1857,7 +2220,7 @@ TQPixmap TQPixmap::xForm( const TQWMatrix &matrix ) const
} else {
xbpl = (w*bpp)/8;
p_inc = dbpl - xbpl;
-#if defined(TQT_MITSHM)
+#if defined(TQT_MITSHM_XFORM)
if ( use_mitshm )
p_inc = xshmimg->bytes_per_line - xbpl;
#endif
@@ -1894,7 +2257,7 @@ TQPixmap TQPixmap::xForm( const TQWMatrix &matrix ) const
TQPixmap pm( w, h );
pm.data->uninit = FALSE;
pm.x11SetScreen( x11Screen() );
-#if defined(TQT_MITSHM)
+#if defined(TQT_MITSHM_XFORM)
if ( use_mitshm ) {
XCopyArea( dpy, xshmpm, pm.handle(), gc, 0, 0, w, h, 0, 0 );
} else {
@@ -1903,7 +2266,7 @@ TQPixmap TQPixmap::xForm( const TQWMatrix &matrix ) const
ZPixmap, 0, (char *)dptr, w, h, 32, 0 );
XPutImage( dpy, pm.handle(), gc, xi, 0, 0, 0, 0, w, h);
qSafeXDestroyImage( xi );
-#if defined(TQT_MITSHM)
+#if defined(TQT_MITSHM_XFORM)
}
#endif
diff --git a/tqtinterface/qt4/src/kernel/tqrichtext.cpp b/tqtinterface/qt4/src/kernel/tqrichtext.cpp
index 8b614d6..00484d6 100644
--- a/tqtinterface/qt4/src/kernel/tqrichtext.cpp
+++ b/tqtinterface/qt4/src/kernel/tqrichtext.cpp
@@ -9028,7 +9028,7 @@ void TQTextCursor::restoreState()
pop();
}
-bool TQTextCursor::place( const TQPoint &p, TQTextParagraph *s, bool link )
+bool TQTextCursor::place( const TQPoint &p, TQTextParagraph *s, bool link, bool loosePlacing, bool matchBetweenCharacters )
{
TQPoint pos( p );
TQRect r;
@@ -9046,7 +9046,7 @@ bool TQTextCursor::place( const TQPoint &p, TQTextParagraph *s, bool link )
str = s;
if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() )
break;
- if ( !s->next() ) {
+ if ( loosePlacing == TRUE && !s->next() ) {
#ifdef TQ_WS_MACX
pos.setX( s->rect().x() + s->rect().width() );
#endif
@@ -9087,7 +9087,7 @@ bool TQTextCursor::place( const TQPoint &p, TQTextParagraph *s, bool link )
if ( pos.x() < x )
pos.setX( x + 1 );
int cw;
- int curpos = s->length()-1;
+ int curpos = -1;
int dist = 10000000;
bool inCustom = FALSE;
while ( i < nextLine ) {
@@ -9109,14 +9109,21 @@ bool TQTextCursor::place( const TQPoint &p, TQTextParagraph *s, bool link )
cpos += cw;
int d = cpos - pos.x();
bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft;
- if ( (TQABS( d ) < dist || (dist == d && dm == TRUE )) && para->string()->validCursorPosition( i ) ) {
+ if ( ( matchBetweenCharacters == TRUE && (TQABS( d ) < dist || (dist == d && dm == TRUE )) && para->string()->validCursorPosition( i ) ) ||
+ ( matchBetweenCharacters == FALSE && ( d == 0 || dm == TRUE ) ) ) {
dist = TQABS( d );
- if ( !link || pos.x() >= x + chr->x )
+ if ( !link || ( pos.x() >= x + chr->x && ( loosePlacing == TRUE || pos.x() < cpos ) ) )
curpos = i;
}
}
i++;
}
+ if ( curpos == -1 ) {
+ if ( loosePlacing == TRUE )
+ curpos = s->length()-1;
+ else
+ return FALSE;
+ }
setIndex( curpos );
#ifndef TQT_NO_TEXTCUSTOMITEM
@@ -13244,6 +13251,9 @@ void TQTextParagraph::drawString( TQPainter &painter, const TQString &str, int s
tmpw = fullSelectionWidth - xleft;
painter.fillRect( xleft, y, tmpw, h, color );
painter.drawText( xstart, y + baseLine, str, start, len, dir );
+ // draw preedit's underline
+ if (selection == TQTextDocument::IMCompositionText)
+ painter.drawLine(xstart, y + baseLine + 1, xstart + w, y + baseLine + 1);
if (selStart != start || selEnd != start + len || selWrap)
painter.restore();
}
diff --git a/tqtinterface/qt4/src/kernel/tqrichtext_p.h b/tqtinterface/qt4/src/kernel/tqrichtext_p.h
index b9cbd98..edb8c76 100644
--- a/tqtinterface/qt4/src/kernel/tqrichtext_p.h
+++ b/tqtinterface/qt4/src/kernel/tqrichtext_p.h
@@ -2523,7 +2523,8 @@ public:
int totalOffsetY() const; // total document offset
bool place( const TQPoint &pos, TQTextParagraph *s ) { return place( pos, s, FALSE ); }
- bool place( const TQPoint &pos, TQTextParagraph *s, bool link );
+ bool place( const TQPoint &pos, TQTextParagraph *s, bool link ) { return place( pos, s, link, TRUE, TRUE ); }
+ bool place( const TQPoint &pos, TQTextParagraph *s, bool link, bool loosePlacing, bool matchBetweenCharacters );
void restoreState();
diff --git a/tqtinterface/qt4/src/kernel/tqt_x11_p.h b/tqtinterface/qt4/src/kernel/tqt_x11_p.h
index e08531d..a33ce01 100644
--- a/tqtinterface/qt4/src/kernel/tqt_x11_p.h
+++ b/tqtinterface/qt4/src/kernel/tqt_x11_p.h
@@ -177,6 +177,11 @@ extern "C" {
#endif // TQT_NO_XRENDER
+#ifndef TQT_NO_XSYNC
+# include <X11/extensions/sync.h>
+#endif // TQT_NO_XSYNC
+
+
#ifndef TQT_NO_XKB
# include <X11/XKBlib.h>
#endif // TQT_NO_XKB
diff --git a/tqtinterface/qt4/src/kernel/tqwidget.cpp b/tqtinterface/qt4/src/kernel/tqwidget.cpp
index 9e60bac..67d0e1b 100644
--- a/tqtinterface/qt4/src/kernel/tqwidget.cpp
+++ b/tqtinterface/qt4/src/kernel/tqwidget.cpp
@@ -5953,8 +5953,24 @@ void TQWidget::setFocus()
if ( isActiveWindow() ) {
TQWidget * prev = tqApp->focus_widget;
if ( prev ) {
- if ( prev != this )
+ // This part is never executed when TQ_WS_X11? Preceding XFocusOut
+ // had already reset focus_widget when received XFocusIn
+
+ // Don't reset input context explicitly here. Whether reset or not
+ // when focusing out is a responsibility of input methods. For
+ // example, Japanese input context should not be reset here. The
+ // context sometimes contains a whole paragraph and has minutes of
+ // lifetime different to ephemeral one in other languages. The
+ // input context should be survived until focused again. So we
+ // delegate the responsibility to input context via
+ // unfocusInputContext().
+ if ( prev != this && prev->isInputMethodEnabled() ) {
+#if 0
prev->resetInputContext();
+#else
+ prev->unfocusInputContext();
+#endif
+ }
}
#if defined(TQ_WS_WIN)
else {
@@ -5962,9 +5978,8 @@ void TQWidget::setFocus()
}
#endif
tqApp->focus_widget = this;
-#if defined(TQ_WS_X11)
- focusInputContext();
-#endif
+ if( isInputMethodEnabled() )
+ focusInputContext();
#if defined(TQ_WS_WIN)
if ( !tqtopLevelWidget()->isPopup() )
@@ -6012,7 +6027,11 @@ void TQWidget::clearFocus()
focusProxy()->clearFocus();
return;
} else if ( hasFocus() ) {
+#if !defined(TQ_WS_X11)
resetInputContext();
+#else
+ unfocusInputContext();
+#endif
TQWidget* w = tqApp->tqfocusWidget();
// clear active focus
tqApp->focus_widget = 0;
@@ -7338,7 +7357,13 @@ bool TQWidget::event( TQEvent *e )
break;
case TQEvent::MouseButtonPress:
+ // Don't reset input context here. Whether reset or not is
+ // a responsibility of input method. reset() will be
+ // called by mouseHandler() of input method if necessary
+ // via mousePressEvent() of text widgets.
+#if 0
resetInputContext();
+#endif
mousePressEvent( (TQMouseEvent*)e );
if ( ! ((TQMouseEvent*)e)->isAccepted() )
return FALSE;
diff --git a/tqtinterface/qt4/src/kernel/tqwidget.h b/tqtinterface/qt4/src/kernel/tqwidget.h
index c027464..65b424e 100644
--- a/tqtinterface/qt4/src/kernel/tqwidget.h
+++ b/tqtinterface/qt4/src/kernel/tqwidget.h
@@ -64,6 +64,10 @@
#endif // TQFONTENGINE_P_H
#endif // USE_QT4
+#if defined(TQ_WS_X11) && !defined(TQT_NO_IM)
+class TQInputContext;
+#endif
+
class TQLayout;
#ifdef USE_QT4
@@ -980,7 +984,19 @@ public:
CGContextRef macCGContext(bool clipped=TRUE) const;
#endif
#endif
-
+#if defined(TQ_WS_X11)
+ enum X11WindowType {
+ X11WindowTypeSelect,
+ X11WindowTypeCombo,
+ X11WindowTypeDND,
+ X11WindowTypeTooltip,
+ X11WindowTypeMenu, // torn-off
+ X11WindowTypeDropdown,
+ X11WindowTypePopup
+ };
+ void x11SetWindowType( X11WindowType type = X11WindowTypeSelect );
+ void x11SetWindowTransient( TQWidget* tqparent );
+#endif
void setWindowOpacity(double level);
double windowOpacity() const;
@@ -1051,6 +1067,18 @@ protected:
int metric( int ) const;
+#if defined(TQ_WS_X11)
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ virtual TQWidget *icHolderWidget();
+#else
+ TQWidget *icHolderWidget();
+#endif
+ TQInputContext *getInputContext();
+ void changeInputContext( const TQString & );
+ void sendMouseEventToInputContext( int x, TQEvent::Type type,
+ TQt::ButtonState button,
+ TQt::ButtonState state );
+#endif
void resetInputContext();
virtual void create( WId = 0, bool initializeWindow = TRUE,
@@ -1082,14 +1110,25 @@ protected:
private Q_SLOTS:
void focusProxyDestroyed();
+#if defined(TQ_WS_X11)
+ void destroyInputContext();
+#endif
private:
void setFontSys( TQFont *f = 0 );
#if defined(TQ_WS_X11)
void createInputContext();
- void destroyInputContext();
void focusInputContext();
+ void unfocusInputContext();
void checkChildrenDnd();
+
+#ifndef TQT_NO_XSYNC
+ void createSyncCounter();
+ void destroySyncCounter();
+ void incrementSyncCounter();
+ void handleSyncRequest( void* ev );
+#endif
+
#elif defined(TQ_WS_MAC)
uint own_id : 1, macDropEnabled : 1;
EventHandlerRef window_event;
@@ -1160,6 +1199,9 @@ private:
#ifndef TQT_NO_LAYOUT
TQLayout *lay_out;
#endif
+#if defined(TQ_WS_X11) && !defined(TQT_NO_IM) && !defined(TQT_NO_IM_EXTENSIONS)
+ TQInputContext *ic; // Input Context
+#endif
TQWExtra *extra;
#if defined(TQ_WS_TQWS)
TQRegion req_region; // Requested region
@@ -1471,7 +1513,13 @@ struct TQ_EXPORT TQTLWExtra {
uint dnd : 1; // DND properties installed
uint uspos : 1; // User defined position
uint ussize : 1; // User defined size
- void *xic; // XIM Input Context
+#if defined(TQT_NO_IM_EXTENSIONS)
+ void *xic; // Input Context
+#endif
+#ifndef TQT_NO_XSYNC
+ ulong syncCounter;
+ uint syncRequestValue[2];
+#endif
#endif
#if defined(TQ_WS_MAC)
WindowGroupRef group;
diff --git a/tqtinterface/qt4/src/kernel/tqwidget_x11.cpp b/tqtinterface/qt4/src/kernel/tqwidget_x11.cpp
index f8c605a..c6e7abb 100644
--- a/tqtinterface/qt4/src/kernel/tqwidget_x11.cpp
+++ b/tqtinterface/qt4/src/kernel/tqwidget_x11.cpp
@@ -83,6 +83,11 @@ extern Atom qt_net_wm_window_type_menu;
extern Atom qt_net_wm_window_type_utility;
extern Atom qt_net_wm_window_type_splash;
extern Atom qt_net_wm_window_type_override;
+extern Atom qt_net_wm_window_type_dropdown_menu;
+extern Atom qt_net_wm_window_type_popup_menu;
+extern Atom qt_net_wm_window_type_combo;
+extern Atom qt_net_wm_window_type_dnd;
+extern Atom qt_net_wm_window_type_tooltip;
extern Atom qt_net_wm_pid;
extern Atom qt_net_wm_user_time;
extern Atom qt_enlightenment_desktop;
@@ -300,11 +305,9 @@ int qt_sip_count( TQWidget* );
bool qt_wstate_iconified( WId );
void qt_updated_rootinfo();
-#ifndef TQT_NO_XIM
-#include "tqinputcontext_p.h"
-
-extern XIM qt_xim;
-extern XIMStyle qt_xim_style;
+#ifndef TQT_NO_IM
+#include "tqinputcontext.h"
+#include "tqinputcontextfactory.h"
#endif
// Paint event clipping magic
@@ -322,6 +325,12 @@ extern bool qt_deferred_map_tqcontains(TQWidget *);
static TQWidget *mouseGrb = 0;
static TQWidget *keyboardGrb = 0;
+#ifndef TQT_NO_XSYNC
+extern Atom qt_net_wm_sync_request_counter;
+extern Atom qt_net_wm_sync_request;
+extern bool qt_use_xsync;
+#endif
+
// defined in qfont_x11.cpp
extern bool qt_has_xft;
@@ -683,10 +692,6 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
x11Colormap() );
#endif // TQT_NO_XFTFREETYPE
- // NET window types
- long net_wintypes[7] = { 0, 0, 0, 0, 0, 0, 0 };
- int curr_wintype = 0;
-
// NET window states
long net_winstates[6] = { 0, 0, 0, 0, 0, 0 };
int curr_winstate = 0;
@@ -708,7 +713,6 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
if ( testWFlags(WStyle_Splash) ) {
if (qt_net_supports(qt_net_wm_window_type_splash)) {
clearWFlags( WX11BypassWM );
- net_wintypes[curr_wintype++] = qt_net_wm_window_type_splash;
} else {
setWFlags( WX11BypassWM | WStyle_Tool | WStyle_NoBorder );
}
@@ -717,27 +721,22 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
mwmhints.decorations = 0L;
mwmhints.flags |= (1L << 1); // MWM_HINTS_DECORATIONS
- if ( testWFlags( WStyle_NoBorder ) ) {
- // override netwm type - quick and easy for KDE noborder
- net_wintypes[curr_wintype++] = qt_net_wm_window_type_override;
- } else {
- if ( testWFlags( WStyle_NormalBorder | WStyle_DialogBorder ) ) {
- mwmhints.decorations |= (1L << 1); // MWM_DECOR_BORDER
- mwmhints.decorations |= (1L << 2); // MWM_DECOR_RESIZEH
- }
+ if ( testWFlags( WStyle_NormalBorder | WStyle_DialogBorder ) ) {
+ mwmhints.decorations |= (1L << 1); // MWM_DECOR_BORDER
+ mwmhints.decorations |= (1L << 2); // MWM_DECOR_RESIZEH
+ }
- if ( testWFlags( WStyle_Title ) )
- mwmhints.decorations |= (1L << 3); // MWM_DECOR_TITLE
+ if ( testWFlags( WStyle_Title ) )
+ mwmhints.decorations |= (1L << 3); // MWM_DECOR_TITLE
- if ( testWFlags( WStyle_SysMenu ) )
- mwmhints.decorations |= (1L << 4); // MWM_DECOR_MENU
+ if ( testWFlags( WStyle_SysMenu ) )
+ mwmhints.decorations |= (1L << 4); // MWM_DECOR_MENU
- if ( testWFlags( WStyle_Minimize ) )
- mwmhints.decorations |= (1L << 5); // MWM_DECOR_MINIMIZE
+ if ( testWFlags( WStyle_Minimize ) )
+ mwmhints.decorations |= (1L << 5); // MWM_DECOR_MINIMIZE
- if ( testWFlags( WStyle_Maximize ) )
- mwmhints.decorations |= (1L << 6); // MWM_DECOR_MAXIMIZE
- }
+ if ( testWFlags( WStyle_Maximize ) )
+ mwmhints.decorations |= (1L << 6); // MWM_DECOR_MAXIMIZE
if (testWFlags(WStyle_Tool)) {
wsa.save_under = True;
@@ -757,23 +756,6 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
}
}
- // ### need a better way to do this
- if (inherits("TQPopupMenu")) {
- // menu netwm type
- net_wintypes[curr_wintype++] = qt_net_wm_window_type_menu;
- } else if (inherits("TQToolBar")) {
- // toolbar netwm type
- net_wintypes[curr_wintype++] = qt_net_wm_window_type_toolbar;
- } else if (testWFlags(WStyle_Customize) && testWFlags(WStyle_Tool)) {
- // utility netwm type
- net_wintypes[curr_wintype++] = qt_net_wm_window_type_utility;
- }
-
- if (dialog) // dialog netwm type
- net_wintypes[curr_wintype++] = qt_net_wm_window_type_dialog;
- // normal netwm type - default
- net_wintypes[curr_wintype++] = qt_net_wm_window_type_normal;
-
// stays on top
if (testWFlags(WStyle_StaysOnTop)) {
net_winstates[curr_winstate++] = qt_net_wm_state_above;
@@ -808,6 +790,7 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
wsa.save_under = True;
XChangeWindowAttributes( dpy, id, CWOverrideRedirect | CWSaveUnder,
&wsa );
+ x11SetWindowType();
} else if ( topLevel && !desktop ) { // top-level widget
TQWidget *p = parentWidget(); // real tqparent
if (p)
@@ -851,11 +834,14 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
XResizeWindow( dpy, id, crect.width(), crect.height() );
XStoreName( dpy, id, tqAppName() );
- Atom protocols[4];
+ Atom protocols[5];
int n = 0;
protocols[n++] = qt_wm_delete_window; // support del window protocol
protocols[n++] = qt_wm_take_focus; // support take focus window protocol
protocols[n++] = qt_net_wm_ping; // support _NET_WM_PING protocol
+#ifndef TQT_NO_XSYNC
+ protocols[n++] = qt_net_wm_sync_request;// support the _NET_WM_SYNC_REQUEST protocol
+#endif
if ( testWFlags( WStyle_ContextHelp ) )
protocols[n++] = qt_net_wm_context_help;
XSetWMProtocols( dpy, id, protocols, n );
@@ -867,12 +853,7 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
else
XDeleteProperty(dpy, id, qt_xa_motif_wm_hints);
- // set _NET_WM_WINDOW_TYPE
- if (curr_wintype > 0)
- XChangeProperty(dpy, id, qt_net_wm_window_type, XA_ATOM, 32, PropModeReplace,
- (unsigned char *) net_wintypes, curr_wintype);
- else
- XDeleteProperty(dpy, id, qt_net_wm_window_type);
+ x11SetWindowType();
// set _NET_WM_WINDOW_STATE
if (curr_winstate > 0)
@@ -886,6 +867,14 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
XChangeProperty(dpy, id, qt_net_wm_pid, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *) &curr_pid, 1);
+#ifndef TQT_NO_XSYNC
+ // set _NET_WM_SYNC_COUNTER
+ createSyncCounter();
+ long counterVal = topData()->syncCounter;
+ XChangeProperty( dpy, id, qt_net_wm_sync_request_counter, XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char*) &counterVal, 1);
+#endif
+
// when we create a toplevel widget, the frame strut should be dirty
fstrut_dirty = 1;
@@ -923,6 +912,10 @@ void TQWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
if ( destroyw )
qt_XDestroyWindow( this, dpy, destroyw );
+
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ ic = 0;
+#endif
}
@@ -981,11 +974,24 @@ void TQWidget::destroy( bool destroyWindow, bool destroySubWindows )
if ( destroyWindow )
qt_XDestroyWindow( this, x11Display(), winid );
}
+#ifndef TQT_NO_XSYNC
+ destroySyncCounter();
+#endif
setWinId( 0 );
extern void qPRCleanup( TQWidget *widget ); // from qapplication_x11.cpp
if ( testWState(WState_Reparented) )
qPRCleanup(this);
+
+ if( this == icHolderWidget() ) {
+ destroyInputContext();
+ } else {
+ // release previous focus information participating with
+ // preedit preservation of qic
+ TQInputContext *qic = getInputContext();
+ if ( qic )
+ qic->releaseComposingWidget( this );
+ }
}
}
@@ -1022,14 +1028,18 @@ void TQWidget::reparentSys( TQWidget *tqparent, WFlags f, const TQPoint &p, bool
XReparentWindow( x11Display(), old_winid,
RootWindow( x11Display(), x11Screen() ), 0, 0 );
- if ( isTopLevel() ) {
- // input contexts are associated with toplevel widgets, so we need
- // destroy the context here. if we are reparenting back to toplevel,
- // then we will have another context created, otherwise we will
- // use our new toplevel's context
+ if ( this == icHolderWidget() ) {
+ // input contexts are sometimes associated with toplevel widgets, so
+ // we need destroy the context here. if we are reparenting back to
+ // toplevel, then we may have another context created, otherwise we
+ // will use our new ic holder's context
destroyInputContext();
}
+#ifndef TQT_NO_XSYNC
+ destroySyncCounter();
+#endif
+
if ( isTopLevel() || !tqparent ) // we are toplevel, or reparenting to toplevel
topData()->parentWinId = 0;
@@ -1131,6 +1141,64 @@ void TQWidget::reparentSys( TQWidget *tqparent, WFlags f, const TQPoint &p, bool
setMouseTracking(mouse_tracking);
}
+// Sets the EWMH (netwm) window type. Needed as a separate function
+// because create() may be too soon in some cases.
+void TQWidget::x11SetWindowType( X11WindowType type )
+{
+ // NET window types
+ long net_wintypes[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ int curr_wintype = 0;
+ if( testWFlags(WType_Desktop))
+ return;
+ if( type == X11WindowTypeSelect ) {
+ if ( testWFlags(WStyle_Splash)) {
+ if (qt_net_supports(qt_net_wm_window_type_splash)) {
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_splash;
+ }
+ } else if (inherits(TQTOOLBAR_OBJECT_NAME_STRING)) {
+ // toolbar netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_toolbar;
+ } else if (testWFlags(WStyle_Customize) && testWFlags(WStyle_Tool)) {
+ // utility netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_utility;
+ } else if (testWFlags(WType_Dialog)) {
+ // dialog netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_dialog;
+ }
+ } else if( type == X11WindowTypeCombo ) {
+ // combo netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_combo;
+ } else if( type == X11WindowTypeDND ) {
+ // dnd netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_dnd;
+ } else if( type == X11WindowTypeDropdown ) {
+ // dropdown netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_dropdown_menu;
+ } else if( type == X11WindowTypePopup ) {
+ // popup netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_popup_menu;
+ } else if( type == X11WindowTypeMenu ) {
+ // menu netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_menu;
+ } else if( type == X11WindowTypeTooltip ) {
+ // tooltip netwm type
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_tooltip;
+ }
+
+ // normal netwm type - default
+ net_wintypes[curr_wintype++] = qt_net_wm_window_type_normal;
+ // set _NET_WM_WINDOW_TYPE
+ if (curr_wintype > 0)
+ XChangeProperty(x11Display(), winId(), qt_net_wm_window_type, XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) net_wintypes, curr_wintype);
+ else
+ XDeleteProperty(x11Display(), winId(), qt_net_wm_window_type);
+}
+
+void TQWidget::x11SetWindowTransient( TQWidget* tqparent )
+{
+ XSetTransientForHint( x11Display(), winId(), tqparent->winId());
+}
/*!
Translates the widget coordinate \a pos to global screen
@@ -1182,7 +1250,8 @@ TQPoint TQWidget::mapFromGlobal( const TQPoint &pos ) const
language input systems.
In the X11 version of TQt, if \a text is TRUE, this method sets the
- XIM "spot" point for complex language input handling.
+ input method focus point in the preedit (XIM "spot" point) for
+ complex language input handling.
The font \a f is a rendering hint to the currently active input method.
If \a f is 0 the widget's font is used.
@@ -1192,22 +1261,15 @@ TQPoint TQWidget::mapFromGlobal( const TQPoint &pos ) const
void TQWidget::setMicroFocusHint(int x, int y, int width, int height,
bool text, TQFont *f )
{
-#ifndef TQT_NO_XIM
+#ifndef TQT_NO_IM
if ( text ) {
- TQWidget* tlw = tqtopLevelWidget();
- TQTLWExtra *topdata = tlw->topData();
-
// trigger input context creation if it hasn't happened already
createInputContext();
- TQInputContext *qic = (TQInputContext *) topdata->xic;
-
- if ( qt_xim && qic ) {
- TQPoint p( x, y );
- TQPoint p2 = mapTo( tqtopLevelWidget(), TQPoint( 0, 0 ) );
- p = mapTo( tqtopLevelWidget(), p);
- qic->setXFontSet( f ? *f : fnt );
- qic->setComposePosition(p.x(), p.y() + height);
- qic->setComposeArea(p2.x(), p2.y(), this->width(), this->height());
+
+ TQInputContext *qic = getInputContext();
+ if(qic) {
+ TQPoint gp = mapToGlobal( TQPoint( x, y ) );
+ qic->setMicroFocus(gp.x(), gp.y(), width, height, f);
}
}
#endif
@@ -2659,13 +2721,21 @@ void TQWidget::deleteSysExtra()
void TQWidget::createTLSysExtra()
{
+#if defined(TQT_NO_IM_EXTENSIONS)
// created lazily
extra->topextra->xic = 0;
+#endif
+#ifndef TQT_NO_XSYNC
+ extra->topextra->syncCounter = 0;
+ extra->topextra->syncRequestValue[0] = 0;
+ extra->topextra->syncRequestValue[1] = 0;
+#endif
}
void TQWidget::deleteTLSysExtra()
{
- destroyInputContext();
+ // don't destroy input context here. it will be destroyed in
+ // TQWidget::destroy() destroyInputContext();
}
/*
@@ -2706,6 +2776,51 @@ void TQWidget::checkChildrenDnd()
}
}
+
+#ifndef TQT_NO_XSYNC
+// create a window's XSyncCounter
+void TQWidget::createSyncCounter()
+{
+ if( !qt_use_xsync || !isTopLevel() || topData()->syncCounter )
+ return;
+ XSyncValue zero;
+ XSyncIntToValue( &zero, 0 );
+ topData()->syncCounter = XSyncCreateCounter( x11Display(), zero );
+}
+
+// destroy a window's XSyncCounter
+void TQWidget::destroySyncCounter()
+{
+ if( !qt_use_xsync || !extra || !extra->topextra
+ || !extra->topextra->syncCounter )
+ return;
+ XSyncDestroyCounter( x11Display(), extra->topextra->syncCounter );
+ extra->topextra->syncCounter = 0;
+}
+
+// increment a window's XSyncCounter
+void TQWidget::incrementSyncCounter()
+{
+ if( qt_use_xsync && topData()->syncCounter &&
+ !(topData()->syncRequestValue[0] == 0 &&
+ topData()->syncRequestValue[1] == 0) ) {
+ XSyncValue val;
+ XSyncIntsToValue( &val, topData()->syncRequestValue[ 0 ], topData()->syncRequestValue[ 1 ] );
+ XSyncSetCounter( x11Display(), topData()->syncCounter, val );
+ topData()->syncRequestValue[0] = topData()->syncRequestValue[1] = 0;
+ }
+}
+
+// handle _NET_WM_SYNC_REQUEST
+void TQWidget::handleSyncRequest( void* ev )
+{
+ XEvent* xev = (XEvent*)ev;
+ topData()->syncRequestValue[ 0 ] = xev->xclient.data.l[ 2 ];
+ topData()->syncRequestValue[ 1 ] = xev->xclient.data.l[ 3 ];
+}
+#endif // TQT_NO_XSYNC
+
+
/*!
\property TQWidget::acceptDrops
\brief whether drop events are enabled for this widget
@@ -2897,76 +3012,256 @@ void TQWidget::updateFrameStrut() const
}
+/*!
+ This function returns the widget holding the TQInputContext
+ instance for this widget. The instance is used for text input to
+ this widget, switching input method, etc.
+
+ By default, this function delegates the role of returning input
+ context holder widget to TQApplication::locateICHolderWidget().
+
+ This definition enables application developer to change the
+ mapping of widgets to TQInputContext instance simply by overriding
+ TQApplication::locateICHolderWidget().
+
+ \sa TQApplication::locateICHolderWidget()
+*/
+TQWidget *TQWidget::icHolderWidget()
+{
+ return tqApp->locateICHolderWidget(this);
+}
+
+
+/*!
+ This function returns the TQInputContext instance for this widget.
+ This instance is used for text input to this widget, etc.
+ It is simply the accessor function.
+*/
+TQInputContext *TQWidget::getInputContext()
+{
+ TQInputContext *qic = 0;
+
+// #if !defined(TQT_NO_IM_EXTENSIONS)
+ if ( isInputMethodEnabled() ) {
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ qic = icHolderWidget()->ic;
+#else
+// {
+ // icHolderWidget is always tqtopLevelWidget
+ TQTLWExtra *topdata = icHolderWidget()->topData();
+ qic = (TQInputContext *)topdata->xic;
+#endif
+ }
+
+ return qic;
+}
+
+
+/*!
+ This function replaces the TQInputContext instance used for text
+ input to this widget. The \a identifierName is the identifier name
+ of newly choosed input method.
+*/
+void TQWidget::changeInputContext( const TQString& identifierName )
+{
+ TQWidget *icWidget = icHolderWidget();
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ TQInputContext **qicp = &icWidget->ic;
+#else
+ TQInputContext **qicp = (TQInputContext **)&icWidget->topData()->xic;
+#endif
+
+ if( *qicp )
+ delete *qicp;
+ // an input context that has the identifierName is generated.
+ TQInputContext *qic = TQInputContextFactory::create( identifierName, icWidget );
+ *qicp = qic;
+ if ( qic ) {
+ TQObject::connect( qic, TQT_SIGNAL(imEventGenerated(TQObject *,TQIMEvent *)),
+ tqApp, TQT_SLOT(postIMEvent(TQObject *,TQIMEvent *)) );
+ TQObject::connect( qic, TQT_SIGNAL(deletionRequested()),
+ icWidget, TQT_SLOT(destroyInputContext()) );
+ }
+}
+
+
+/*!
+ \internal
+ This is an internal function, you should never call this.
+
+ This function is called to generate an input context
+ according to a configuration for default input method
+
+ When TQT_NO_IM_EXTENSIONS is not set, input context is
+ generated only when isInputMethodEnabled() returns TRUE.
+*/
void TQWidget::createInputContext()
{
- TQWidget *tlw = tqtopLevelWidget();
- TQTLWExtra *topdata = tlw->topData();
+// #if !defined(TQT_NO_IM_EXTENSIONS)
+ if( !isInputMethodEnabled() || TQApplication::closingDown() )
+ return;
+// #endif
-#ifndef TQT_NO_XIM
- if (qt_xim) {
- if (! topdata->xic) {
- TQInputContext *qic = new TQInputContext(tlw);
- topdata->xic = (void *) qic;
- }
- } else
-#endif // TQT_NO_XIM
- {
- // qDebug("TQWidget::createInputContext: no xim");
- topdata->xic = 0;
- }
+ TQWidget *icWidget = icHolderWidget();
+#ifndef TQT_NO_IM
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ TQInputContext **qicp = &icWidget->ic;
+#else
+ TQInputContext **qicp = (TQInputContext **)&icWidget->topData()->xic;
+#endif
+
+ if ( ! *qicp ) {
+ // an input context of the default input method is generated.
+ TQInputContext *qic = TQInputContextFactory::create( TQApplication::defaultInputMethod(), icWidget );
+
+ *qicp = qic;
+ if ( qic ) {
+ TQObject::connect( qic, TQT_SIGNAL(imEventGenerated(TQObject *,TQIMEvent *)),
+ tqApp, TQT_SLOT(postIMEvent(TQObject *,TQIMEvent *)) );
+ TQObject::connect( qic, TQT_SIGNAL(deletionRequested()),
+ icWidget, TQT_SLOT(destroyInputContext()) );
+ }
+ }
+#endif // TQT_NO_IM
}
+/*!
+ \internal
+
+ This slot is used to destroy the input context that belonging
+ to the widget itself, so icHolderWidget()->ic is not fetched.
+
+ \sa TQInputContext::deletionRequested()
+*/
void TQWidget::destroyInputContext()
{
-#ifndef TQT_NO_XIM
- TQInputContext *qic = (TQInputContext *) extra->topextra->xic;
- delete qic;
-#endif // TQT_NO_XIM
- extra->topextra->xic = 0;
+#ifndef TQT_NO_IM
+#if !defined(TQT_NO_IM_EXTENSIONS)
+ TQInputContext **qicp = &ic;
+#else
+ if ( ! extra || ! extra->topextra )
+ return;
+
+ TQInputContext **qicp = (TQInputContext **)&extra->topextra->xic;
+#endif
+
+ if( *qicp )
+ delete *qicp;
+
+ *qicp = 0;
+#endif // TQT_NO_IM
}
/*!
- This function is called when the user finishes input composition,
- e.g. changes focus to another widget, moves the cursor, etc.
+ This function is called when text widgets need to be neutral state to
+ execute text operations properly. See qlineedit.cpp and qtextedit.cpp as
+ example.
+
+ Ordinary reset that along with changing focus to another widget,
+ moving the cursor, etc, is implicitly handled via
+ unfocusInputContext() because whether reset or not when such
+ situation is a responsibility of input methods. So we delegate the
+ responsibility to the input context via unfocusInputContext(). See
+ 'Preedit preservation' section of the class description of
+ TQInputContext for further information.
+
+ \sa TQInputContext, unfocusInputContext(), TQInputContext::unsetFocus()
*/
void TQWidget::resetInputContext()
{
-#ifndef TQT_NO_XIM
- if ((qt_xim_style & XIMPreeditCallbacks) && hasFocus()) {
- TQWidget *tlw = tqtopLevelWidget();
- TQTLWExtra *topdata = tlw->topData();
+#ifndef TQT_NO_IM
+ // trigger input context creation if it hasn't happened already
+ createInputContext();
+
+ TQInputContext *qic = getInputContext();
+ if( qic )
+ qic->reset();
+#endif // TQT_NO_IM
+}
+
+
+/*!
+ \internal
+ This is an internal function, you should never call this.
+
+ This function is called to focus associated input context. The
+ code intends to eliminate duplicate focus for the context even if
+ the context is shared between widgets
+
+ \sa TQInputContext::setFocus()
+ */
+void TQWidget::focusInputContext()
+{
+#ifndef TQT_NO_IM
+ TQWidget* tlw = tqtopLevelWidget();
+ if (!tlw->isPopup() || isInputMethodEnabled()) {
// trigger input context creation if it hasn't happened already
createInputContext();
- if (topdata->xic) {
- TQInputContext *qic = (TQInputContext *) topdata->xic;
- qic->reset();
+ TQInputContext *qic = getInputContext();
+ if ( qic ) {
+ if( qic->tqfocusWidget() != this ) {
+ qic->setFocusWidget( this );
+ qic->setFocus();
+ }
}
}
-#endif // TQT_NO_XIM
+#endif // TQT_NO_IM
}
-void TQWidget::focusInputContext()
-{
-#ifndef TQT_NO_XIM
- TQWidget *tlw = tqtopLevelWidget();
- if (!tlw->isPopup() || isInputMethodEnabled()) {
- TQTLWExtra *topdata = tlw->topData();
+/*!
+ \internal
+ This is an internal function, you should never call this.
- // trigger input context creation if it hasn't happened already
- createInputContext();
+ This function is called to remove focus from associated input
+ context.
- if (topdata->xic) {
- TQInputContext *qic = (TQInputContext *) topdata->xic;
- qic->setFocus();
- }
+ \sa TQInputContext::unsetFocus()
+ */
+void TQWidget::unfocusInputContext()
+{
+#ifndef TQT_NO_IM
+ // trigger input context creation if it hasn't happened already
+ createInputContext();
+
+ TQInputContext *qic = getInputContext();
+ if ( qic ) {
+ // may be caused reset() in some input methods
+ qic->unsetFocus();
+ qic->setFocusWidget( 0 );
}
-#endif // TQT_NO_XIM
+#endif // TQT_NO_IM
}
+
+
+/*!
+ This function is called to send mouse event to associated input
+ context by derived text widgets. A derived text widget must be
+ calculate \a x as character offset at the mouse cursor in the
+ preedit.
+
+ \sa TQInputContext::mouseHandler()
+ */
+void TQWidget::sendMouseEventToInputContext( int x, TQEvent::Type type,
+ TQt::ButtonState button,
+ TQt::ButtonState state )
+{
+#ifndef TQT_NO_IM
+ // trigger input context creation if it hasn't happened already
+ createInputContext();
+
+ TQInputContext *qic = getInputContext();
+ if ( qic ) {
+ // may be causing reset() in some input methods
+ qic->mouseHandler( x, type, button, state );
+ }
+#endif // TQT_NO_IM
+}
+
void TQWidget::setWindowOpacity(double)
{