summaryrefslogtreecommitdiffstats
path: root/src/kernel/qwidget_x11.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
commitbd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch)
tree7a520322212d48ebcb9fbe1087e7fca28b76185c /src/kernel/qwidget_x11.cpp
downloadqt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz
qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip
Add Qt3 development HEAD version
Diffstat (limited to 'src/kernel/qwidget_x11.cpp')
-rw-r--r--src/kernel/qwidget_x11.cpp3039
1 files changed, 3039 insertions, 0 deletions
diff --git a/src/kernel/qwidget_x11.cpp b/src/kernel/qwidget_x11.cpp
new file mode 100644
index 0000000..02fdebf
--- /dev/null
+++ b/src/kernel/qwidget_x11.cpp
@@ -0,0 +1,3039 @@
+/****************************************************************************
+**
+** Implementation of QWidget and QWindow classes for X11
+**
+** Created : 931031
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the kernel module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qnamespace.h"
+#include "qpaintdevicemetrics.h"
+#include "qpainter.h"
+#include "qbitmap.h"
+#include "qobjectlist.h"
+#include "qlayout.h"
+#include "qtextcodec.h"
+#include "qdatetime.h"
+#include "qcursor.h"
+#include "qt_x11_p.h"
+#include <stdlib.h>
+
+// NOT REVISED
+
+// defined in qapplication_x11.cpp
+extern Window qt_x11_wm_client_leader;
+extern void qt_x11_create_wm_client_leader();
+
+// defined in qapplication_x11.cpp
+void qt_insert_sip( QWidget*, int, int );
+int qt_sip_count( QWidget* );
+bool qt_wstate_iconified( WId );
+void qt_updated_rootinfo();
+
+#ifndef QT_NO_IM
+#include "qinputcontext.h"
+#include "qinputcontextfactory.h"
+#endif
+
+// Paint event clipping magic
+extern void qt_set_paintevent_clipping( QPaintDevice* dev, const QRegion& region);
+extern void qt_clear_paintevent_clipping();
+
+extern bool qt_dnd_enable( QWidget* w, bool on );
+extern bool qt_nograb();
+
+// defined in qapplication_x11.cpp
+extern void qt_deferred_map_add( QWidget* );
+extern void qt_deferred_map_take( QWidget* );
+extern bool qt_deferred_map_contains(QWidget *);
+
+static QWidget *mouseGrb = 0;
+static QWidget *keyboardGrb = 0;
+
+// defined in qapplication_x11.cpp
+extern Time qt_x_time;
+extern Time qt_x_user_time;
+
+#ifndef QT_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;
+
+int qt_x11_create_desktop_on_screen = -1;
+
+/*****************************************************************************
+ QWidget member functions
+ *****************************************************************************/
+
+// defined in qapplication_x11.cpp
+extern Atom qt_wm_state;
+extern Atom qt_wm_change_state;
+extern Atom qt_wm_delete_window;
+extern Atom qt_wm_take_focus;
+extern Atom qt_wm_client_leader;
+extern Atom qt_window_role;
+extern Atom qt_sm_client_id;
+extern Atom qt_utf8_string;
+extern Atom qt_net_wm_context_help;
+extern Atom qt_net_wm_ping;
+extern Atom qt_xa_motif_wm_hints;
+extern Atom qt_net_wm_name;
+extern Atom qt_net_wm_icon_name;
+extern Atom qt_net_wm_state;
+extern Atom qt_net_wm_state_modal;
+extern Atom qt_net_wm_state_max_v;
+extern Atom qt_net_wm_state_max_h;
+extern Atom qt_net_wm_state_fullscreen;
+extern Atom qt_net_wm_state_above;
+extern Atom qt_net_wm_state_stays_on_top;
+extern Atom qt_net_wm_window_type;
+extern Atom qt_net_wm_window_type_normal;
+extern Atom qt_net_wm_window_type_dialog;
+extern Atom qt_net_wm_window_type_toolbar;
+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;
+extern Atom qt_net_virtual_roots;
+extern bool qt_broken_wm;
+
+// defined in qapplication_x11.cpp
+extern bool qt_net_supports(Atom);
+extern unsigned long *qt_net_virtual_root_list;
+
+#if defined (QT_TABLET_SUPPORT)
+extern XDevice *devStylus;
+extern XDevice *devEraser;
+extern XEventClass event_list_stylus[7];
+extern XEventClass event_list_eraser[7];
+extern int qt_curr_events_stylus;
+extern int qt_curr_events_eraser;
+#endif
+
+const uint stdWidgetEventMask = // X event mask
+ (uint)(
+ KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask |
+ KeymapStateMask |
+ ButtonMotionMask |
+ EnterWindowMask | LeaveWindowMask |
+ FocusChangeMask |
+ ExposureMask |
+ PropertyChangeMask |
+ StructureNotifyMask
+ );
+
+const uint stdDesktopEventMask = // X event mask
+ (uint)(
+ KeymapStateMask |
+ EnterWindowMask | LeaveWindowMask |
+ PropertyChangeMask
+ );
+
+
+/*
+ The qt_ functions below are implemented in qwidgetcreate_x11.cpp.
+*/
+
+Window qt_XCreateWindow( const QWidget *creator,
+ Display *display, Window parent,
+ int x, int y, uint w, uint h,
+ int borderwidth, int depth,
+ uint windowclass, Visual *visual,
+ ulong valuemask, XSetWindowAttributes *attributes );
+Window qt_XCreateSimpleWindow( const QWidget *creator,
+ Display *display, Window parent,
+ int x, int y, uint w, uint h, int borderwidth,
+ ulong border, ulong background );
+void qt_XDestroyWindow( const QWidget *destroyer,
+ Display *display, Window window );
+
+Q_EXPORT void qt_x11_enforce_cursor( QWidget * w )
+{
+ if ( w->testWState( Qt::WState_OwnCursor ) ) {
+ QCursor * oc = QApplication::overrideCursor();
+ if ( oc ) {
+ XDefineCursor( w->x11Display(), w->winId(), oc->handle() );
+ } else if ( w->isEnabled() ) {
+ XDefineCursor( w->x11Display(), w->winId(), w->cursor().handle() );
+ } else {
+ // enforce the windows behavior of clearing the cursor on
+ // disabled widgets
+ XDefineCursor( w->x11Display(), w->winId(), None );
+ }
+ } else {
+ XDefineCursor( w->x11Display(), w->winId(), None );
+ }
+}
+
+Q_EXPORT void qt_wait_for_window_manager( QWidget* w )
+{
+ QApplication::flushX();
+ XEvent ev;
+ QTime t;
+ t.start();
+ while ( !XCheckTypedWindowEvent( w->x11Display(), w->winId(), ReparentNotify, &ev ) ) {
+ if ( XCheckTypedWindowEvent( w->x11Display(), w->winId(), MapNotify, &ev ) )
+ break;
+ if ( t.elapsed() > 500 )
+ return; // give up, no event available
+ qApp->syncX(); // non-busy wait
+ }
+ qApp->x11ProcessEvent( &ev );
+ if ( XCheckTypedWindowEvent( w->x11Display(), w->winId(), ConfigureNotify, &ev ) )
+ qApp->x11ProcessEvent( &ev );
+}
+
+static void qt_net_change_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
+{
+ if (w->isShown()) {
+ // managed by WM
+ XEvent e;
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = qt_net_wm_state;
+ e.xclient.display = w->x11Display();
+ e.xclient.window = w->winId();
+ e.xclient.format = 32;
+ e.xclient.data.l[ 0 ] = set ? 1 : 0;
+ e.xclient.data.l[ 1 ] = one;
+ e.xclient.data.l[ 2 ] = two;
+ e.xclient.data.l[ 3 ] = 0;
+ e.xclient.data.l[ 4 ] = 0;
+ XSendEvent(w->x11Display(), RootWindow(w->x11Display(), w->x11Screen()),
+ False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
+ } else {
+ Atom ret;
+ int format = 0, status;
+ unsigned char *data = 0;
+ unsigned long nitems = 0, after = 0;
+ Atom *old_states = 0;
+ status = XGetWindowProperty(w->x11Display(), w->winId(),
+ qt_net_wm_state, 0, 1024, False,
+ XA_ATOM, &ret, &format, &nitems,
+ &after, &data);
+ if (status == Success && ret == XA_ATOM && format == 32 && nitems > 0)
+ old_states = (Atom *) data;
+ else
+ nitems = 0;
+
+ Atom *new_states = new Atom[nitems + 2];
+ int i, j = 0;
+ for (i = 0; i < (int)nitems; ++i) {
+ if (old_states[i] && old_states[i] != one && old_states[i] != two)
+ new_states[j++] = old_states[i];
+ }
+
+ if (set) {
+ if (one) new_states[j++] = one;
+ if (two) new_states[j++] = two;
+ }
+
+ if (j)
+ XChangeProperty(w->x11Display(), w->winId(), qt_net_wm_state, XA_ATOM, 32,
+ PropModeReplace, (uchar *) new_states, j);
+ else
+ XDeleteProperty(w->x11Display(), w->winId(), qt_net_wm_state);
+
+ delete [] new_states;
+ if (data) XFree(data);
+ }
+}
+
+/*!
+ Creates a new widget window if \a window is 0, otherwise sets the
+ widget's window to \a window.
+
+ Initializes the window (sets the geometry etc.) if \a
+ initializeWindow is TRUE. If \a initializeWindow is FALSE, no
+ initialization is performed. This parameter only makes sense if \a
+ window is a valid window.
+
+ Destroys the old window if \a destroyOldWindow is TRUE. If \a
+ destroyOldWindow is FALSE, you are responsible for destroying the
+ window yourself (using platform native code).
+
+ The QWidget constructor calls create(0,TRUE,TRUE) to create a
+ window for this widget.
+*/
+
+void QWidget::create( WId window, bool initializeWindow, bool destroyOldWindow)
+{
+ if ( testWState(WState_Created) && window == 0 )
+ return;
+
+ // set created flag
+ setWState( WState_Created );
+
+ bool popup = testWFlags(WType_Popup);
+ bool dialog = testWFlags(WType_Dialog);
+ bool desktop = testWFlags(WType_Desktop);
+
+ // top-level widget
+ if ( !parentWidget() || parentWidget()->isDesktop() )
+ setWFlags( WType_TopLevel );
+
+ // these are top-level, too
+ if ( dialog || popup || desktop || testWFlags(WStyle_Splash))
+ setWFlags( WType_TopLevel );
+
+ // a popup stays on top
+ if ( popup )
+ setWFlags(WStyle_StaysOnTop);
+
+ bool topLevel = testWFlags(WType_TopLevel);
+ Window parentw, destroyw = 0;
+ WId id;
+
+ // always initialize
+ if ( !window )
+ initializeWindow = TRUE;
+
+ if ( desktop &&
+ qt_x11_create_desktop_on_screen >= 0 &&
+ qt_x11_create_desktop_on_screen != x11Screen() ) {
+ // desktop on a certain screen other than the default requested
+ QPaintDeviceX11Data* xd = getX11Data( TRUE );
+ xd->x_screen = qt_x11_create_desktop_on_screen;
+ xd->x_depth = QPaintDevice::x11AppDepth( xd->x_screen );
+ xd->x_cells = QPaintDevice::x11AppCells( xd->x_screen );
+ xd->x_colormap = QPaintDevice::x11AppColormap( xd->x_screen );
+ xd->x_defcolormap = QPaintDevice::x11AppDefaultColormap( xd->x_screen );
+ xd->x_visual = QPaintDevice::x11AppVisual( xd->x_screen );
+ xd->x_defvisual = QPaintDevice::x11AppDefaultVisual( xd->x_screen );
+ setX11Data( xd );
+ } else if ( parentWidget() && parentWidget()->x11Screen() != x11Screen() ) {
+ // if we have a parent widget, move to its screen if necessary
+ QPaintDeviceX11Data* xd = getX11Data( TRUE );
+ xd->x_screen = parentWidget()->x11Screen();
+ xd->x_depth = QPaintDevice::x11AppDepth( xd->x_screen );
+ xd->x_cells = QPaintDevice::x11AppCells( xd->x_screen );
+ xd->x_colormap = QPaintDevice::x11AppColormap( xd->x_screen );
+ xd->x_defcolormap = QPaintDevice::x11AppDefaultColormap( xd->x_screen );
+ xd->x_visual = QPaintDevice::x11AppVisual( xd->x_screen );
+ xd->x_defvisual = QPaintDevice::x11AppDefaultVisual( xd->x_screen );
+ setX11Data( xd );
+ }
+
+ //get display, screen number, root window and desktop geometry for
+ //the current screen
+ Display *dpy = x11Display();
+ int scr = x11Screen();
+ Window root_win = RootWindow( dpy, scr );
+ int sw = DisplayWidth(dpy,scr);
+ int sh = DisplayHeight(dpy,scr);
+
+ if ( desktop ) { // desktop widget
+ dialog = popup = FALSE; // force these flags off
+ crect.setRect( 0, 0, sw, sh );
+ } else if ( topLevel ) { // calc pos/size from screen
+ crect.setRect( sw/4, 3*sh/10, sw/2, 4*sh/10 );
+ } else { // child widget
+ crect.setRect( 0, 0, 100, 30 );
+ }
+
+ parentw = topLevel ? root_win : parentWidget()->winId();
+
+ XSetWindowAttributes wsa;
+
+ if ( window ) { // override the old window
+ if ( destroyOldWindow )
+ destroyw = winid;
+ id = window;
+ setWinId( window );
+ XWindowAttributes a;
+ XGetWindowAttributes( dpy, window, &a );
+ crect.setRect( a.x, a.y, a.width, a.height );
+
+ if ( a.map_state == IsUnmapped )
+ clearWState( WState_Visible );
+ else
+ setWState( WState_Visible );
+
+ QPaintDeviceX11Data* xd = getX11Data( TRUE );
+
+ // find which screen the window is on...
+ xd->x_screen = QPaintDevice::x11AppScreen(); // by default, use the default :)
+ int i;
+ for ( i = 0; i < ScreenCount( dpy ); i++ ) {
+ if ( RootWindow( dpy, i ) == a.root ) {
+ xd->x_screen = i;
+ break;
+ }
+ }
+
+ xd->x_depth = a.depth;
+ xd->x_cells = DisplayCells( dpy, xd->x_screen );
+ xd->x_visual = a.visual;
+ xd->x_defvisual = ( XVisualIDFromVisual( a.visual ) ==
+ XVisualIDFromVisual( (Visual*)x11AppVisual(x11Screen()) ) );
+ xd->x_colormap = a.colormap;
+ xd->x_defcolormap = ( a.colormap == x11AppColormap( x11Screen() ) );
+ setX11Data( xd );
+ } else if ( desktop ) { // desktop widget
+ id = (WId)parentw; // id = root window
+ QWidget *otherDesktop = find( id ); // is there another desktop?
+ if ( otherDesktop && otherDesktop->testWFlags(WPaintDesktop) ) {
+ otherDesktop->setWinId( 0 ); // remove id from widget mapper
+ setWinId( id ); // make sure otherDesktop is
+ otherDesktop->setWinId( id ); // found first
+ } else {
+ setWinId( id );
+ }
+ } else {
+ if ( x11DefaultVisual() && x11DefaultColormap() ) {
+ id = (WId)qt_XCreateSimpleWindow( this, dpy, parentw,
+ crect.left(), crect.top(),
+ crect.width(), crect.height(),
+ 0,
+ black.pixel(x11Screen()),
+ bg_col.pixel(x11Screen()) );
+ } else {
+ wsa.background_pixel = bg_col.pixel(x11Screen());
+ wsa.border_pixel = black.pixel(x11Screen());
+ wsa.colormap = (Colormap)x11Colormap();
+ id = (WId)qt_XCreateWindow( this, dpy, parentw,
+ crect.left(), crect.top(),
+ crect.width(), crect.height(),
+ 0, x11Depth(), InputOutput,
+ (Visual*)x11Visual(),
+ CWBackPixel|CWBorderPixel|CWColormap,
+ &wsa );
+ }
+
+ setWinId( id ); // set widget id/handle + hd
+ }
+
+#ifndef QT_NO_XFTFREETYPE
+ if (rendhd) {
+ XftDrawDestroy( (XftDraw *) rendhd );
+ rendhd = 0;
+ }
+
+ if ( qt_has_xft )
+ rendhd = (HANDLE) XftDrawCreate( dpy, id, (Visual *) x11Visual(),
+ x11Colormap() );
+#endif // QT_NO_XFTFREETYPE
+
+ // NET window states
+ long net_winstates[6] = { 0, 0, 0, 0, 0, 0 };
+ int curr_winstate = 0;
+
+ struct {
+ ulong flags, functions, decorations;
+ long input_mode;
+ ulong status;
+ } mwmhints;
+
+ mwmhints.flags = mwmhints.functions = 0L;
+ mwmhints.decorations = (1L << 0); // MWM_DECOR_ALL
+ mwmhints.input_mode = 0L;
+ mwmhints.status = 0L;
+
+ if (topLevel && ! (desktop || popup)) {
+ ulong wsa_mask = 0;
+
+ if ( testWFlags(WStyle_Splash) ) {
+ if (qt_net_supports(qt_net_wm_window_type_splash)) {
+ clearWFlags( WX11BypassWM );
+ } else {
+ setWFlags( WX11BypassWM | WStyle_Tool | WStyle_NoBorder );
+ }
+ }
+ if (testWFlags(WStyle_Customize)) {
+ mwmhints.decorations = 0L;
+ mwmhints.flags |= (1L << 1); // MWM_HINTS_DECORATIONS
+
+ 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_SysMenu ) )
+ mwmhints.decorations |= (1L << 4); // MWM_DECOR_MENU
+
+ 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_Tool)) {
+ wsa.save_under = True;
+ wsa_mask |= CWSaveUnder;
+ }
+ } else if (testWFlags(WType_Dialog)) {
+ setWFlags(WStyle_NormalBorder | WStyle_Title |
+ WStyle_SysMenu | WStyle_ContextHelp);
+ } else {
+ setWFlags(WStyle_NormalBorder | WStyle_Title |
+ WStyle_MinMax | WStyle_SysMenu);
+
+ // maximized netwm state
+ if (testWFlags(WState_Maximized)) {
+ net_winstates[curr_winstate++] = qt_net_wm_state_max_v;
+ net_winstates[curr_winstate++] = qt_net_wm_state_max_h;
+ }
+ }
+
+ // stays on top
+ if (testWFlags(WStyle_StaysOnTop)) {
+ net_winstates[curr_winstate++] = qt_net_wm_state_above;
+ net_winstates[curr_winstate++] = qt_net_wm_state_stays_on_top;
+ }
+
+ if (testWFlags(WShowModal)) {
+ mwmhints.input_mode = 3L; // MWM_INPUT_FULL_APPLICATION_MODAL
+ mwmhints.flags |= (1L << 2); // MWM_HINTS_INPUT_MODE
+
+ net_winstates[curr_winstate++] = qt_net_wm_state_modal;
+ }
+
+ if ( testWFlags( WX11BypassWM ) ) {
+ wsa.override_redirect = True;
+ wsa_mask |= CWOverrideRedirect;
+ }
+
+ if ( wsa_mask && initializeWindow )
+ XChangeWindowAttributes( dpy, id, wsa_mask, &wsa );
+ } else {
+ if (! testWFlags(WStyle_Customize))
+ setWFlags(WStyle_NormalBorder | WStyle_Title |
+ WStyle_MinMax | WStyle_SysMenu);
+ }
+
+
+ if ( !initializeWindow ) {
+ // do no initialization
+ } else if ( popup ) { // popup widget
+ wsa.override_redirect = True;
+ wsa.save_under = True;
+ XChangeWindowAttributes( dpy, id, CWOverrideRedirect | CWSaveUnder,
+ &wsa );
+ x11SetWindowType();
+ } else if ( topLevel && !desktop ) { // top-level widget
+ QWidget *p = parentWidget(); // real parent
+ if (p)
+ p = p->topLevelWidget();
+
+ if (dialog || testWFlags(WStyle_DialogBorder) || testWFlags(WStyle_Tool)) {
+ if ( p )
+ XSetTransientForHint( dpy, id, p->winId() );
+ else // application-modal
+ XSetTransientForHint( dpy, id, root_win );
+ }
+
+ // find the real client leader, i.e. a toplevel without parent
+ while ( p && p->parentWidget())
+ p = p->parentWidget()->topLevelWidget();
+
+ XSizeHints size_hints;
+ size_hints.flags = USSize | PSize | PWinGravity;
+ size_hints.x = crect.left();
+ size_hints.y = crect.top();
+ size_hints.width = crect.width();
+ size_hints.height = crect.height();
+ size_hints.win_gravity =
+ QApplication::reverseLayout() ? NorthEastGravity : NorthWestGravity;
+
+ XWMHints wm_hints; // window manager hints
+ wm_hints.input = True;
+ wm_hints.initial_state = NormalState;
+ wm_hints.flags = InputHint | StateHint;
+ if ( !qt_x11_wm_client_leader )
+ qt_x11_create_wm_client_leader();
+
+ wm_hints.window_group = qt_x11_wm_client_leader;
+ wm_hints.flags |= WindowGroupHint;
+
+ XClassHint class_hint;
+ class_hint.res_name = (char *) qAppName(); // application name
+ class_hint.res_class = (char *) qAppClass(); // application class
+
+ XSetWMProperties( dpy, id, 0, 0, 0, 0, &size_hints, &wm_hints, &class_hint );
+
+ XResizeWindow( dpy, id, crect.width(), crect.height() );
+ XStoreName( dpy, id, qAppName() );
+ 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 QT_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 );
+
+ // set mwm hints
+ if ( mwmhints.flags != 0l )
+ XChangeProperty(dpy, id, qt_xa_motif_wm_hints, qt_xa_motif_wm_hints, 32,
+ PropModeReplace, (unsigned char *) &mwmhints, 5);
+ else
+ XDeleteProperty(dpy, id, qt_xa_motif_wm_hints);
+
+ x11SetWindowType();
+
+ // set _NET_WM_WINDOW_STATE
+ if (curr_winstate > 0)
+ XChangeProperty(dpy, id, qt_net_wm_state, XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) net_winstates, curr_winstate);
+ else
+ XDeleteProperty(dpy, id, qt_net_wm_state);
+
+ // set _NET_WM_PID
+ long curr_pid = getpid();
+ XChangeProperty(dpy, id, qt_net_wm_pid, XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &curr_pid, 1);
+
+#ifndef QT_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;
+
+ // declare the widget's object name as window role
+ XChangeProperty( dpy, id,
+ qt_window_role, XA_STRING, 8, PropModeReplace,
+ (unsigned char *)name(), qstrlen( name() ) );
+
+ // set client leader property
+ XChangeProperty( dpy, id, qt_wm_client_leader,
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *)&qt_x11_wm_client_leader, 1 );
+ } else {
+ // non-toplevel widgets don't have a frame, so no need to
+ // update the strut
+ fstrut_dirty = 0;
+ }
+
+ if ( initializeWindow ) {
+ // don't erase when resizing
+ wsa.bit_gravity =
+ QApplication::reverseLayout() ? NorthEastGravity : NorthWestGravity;
+ XChangeWindowAttributes( dpy, id, CWBitGravity, &wsa );
+ }
+
+ setWState( WState_MouseTracking );
+ setMouseTracking( FALSE ); // also sets event mask
+ if ( desktop ) {
+ setWState( WState_Visible );
+ } else if ( topLevel ) { // set X cursor
+ setWState( WState_OwnCursor );
+ if ( initializeWindow )
+ qt_x11_enforce_cursor( this );
+ }
+
+ if ( destroyw )
+ qt_XDestroyWindow( this, dpy, destroyw );
+
+#if !defined(QT_NO_IM_EXTENSIONS)
+ ic = 0;
+#endif
+}
+
+
+/*!
+ Frees up window system resources. Destroys the widget window if \a
+ destroyWindow is TRUE.
+
+ destroy() calls itself recursively for all the child widgets,
+ passing \a destroySubWindows for the \a destroyWindow parameter.
+ To have more control over destruction of subwidgets, destroy
+ subwidgets selectively first.
+
+ This function is usually called from the QWidget destructor.
+*/
+
+void QWidget::destroy( bool destroyWindow, bool destroySubWindows )
+{
+ deactivateWidgetCleanup();
+ if ( testWState(WState_Created) ) {
+ clearWState( WState_Created );
+ if ( children() ) {
+ QObjectListIt it(*children());
+ register QObject *obj;
+ while ( (obj=it.current()) ) { // destroy all widget children
+ ++it;
+ if ( obj->isWidgetType() )
+ ((QWidget*)obj)->destroy(destroySubWindows,
+ destroySubWindows);
+ }
+ }
+ if ( mouseGrb == this )
+ releaseMouse();
+ if ( keyboardGrb == this )
+ releaseKeyboard();
+ if ( isTopLevel() )
+ qt_deferred_map_take( this );
+ if ( testWFlags(WShowModal) ) // just be sure we leave modal
+ qt_leave_modal( this );
+ else if ( testWFlags(WType_Popup) )
+ qApp->closePopup( this );
+
+#ifndef QT_NO_XFTFREETYPE
+ if ( rendhd) {
+ if ( destroyWindow )
+ XftDrawDestroy( (XftDraw *) rendhd );
+ else
+ free( (void*) rendhd );
+ rendhd = 0;
+ }
+#endif // QT_NO_XFTFREETYPE
+
+ if ( testWFlags(WType_Desktop) ) {
+ if ( acceptDrops() )
+ qt_dnd_enable( this, FALSE );
+ } else {
+ if ( destroyWindow )
+ qt_XDestroyWindow( this, x11Display(), winid );
+ }
+#ifndef QT_NO_XSYNC
+ destroySyncCounter();
+#endif
+ setWinId( 0 );
+
+ extern void qPRCleanup( QWidget *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
+ QInputContext *qic = getInputContext();
+ if ( qic )
+ qic->releaseComposingWidget( this );
+ }
+ }
+}
+
+void QWidget::reparentSys( QWidget *parent, WFlags f, const QPoint &p, bool showIt )
+{
+ extern void qPRCreate( const QWidget *, Window );
+
+ Display *dpy = x11Display();
+ QCursor oldcurs;
+ bool setcurs = testWState(WState_OwnCursor);
+ if ( setcurs ) {
+ oldcurs = cursor();
+ unsetCursor();
+ }
+
+ // dnd unregister (we will register again below)
+ bool accept_drops = acceptDrops();
+ setAcceptDrops( FALSE );
+
+ // clear mouse tracking, re-enabled below
+ bool mouse_tracking = hasMouseTracking();
+ clearWState(WState_MouseTracking);
+
+ QWidget* oldtlw = topLevelWidget();
+ QWidget *oldparent = parentWidget();
+ WId old_winid = winid;
+ if ( testWFlags(WType_Desktop) )
+ old_winid = 0;
+ setWinId( 0 );
+
+ // hide and reparent our own window away. Otherwise we might get
+ // destroyed when emitting the child remove event below. See QWorkspace.
+ XUnmapWindow( x11Display(), old_winid );
+ XReparentWindow( x11Display(), old_winid,
+ RootWindow( x11Display(), x11Screen() ), 0, 0 );
+
+ 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 QT_NO_XSYNC
+ destroySyncCounter();
+#endif
+
+ if ( isTopLevel() || !parent ) // we are toplevel, or reparenting to toplevel
+ topData()->parentWinId = 0;
+
+ if ( parent != parentObj ) {
+ if ( parentObj ) // remove from parent
+ parentObj->removeChild( this );
+ if ( parent ) // insert into new parent
+ parent->insertChild( this );
+ }
+ bool enable = isEnabled(); // remember status
+ FocusPolicy fp = focusPolicy();
+ QSize s = size();
+ QPixmap *bgp = (QPixmap *)backgroundPixmap();
+ QColor bgc = bg_col; // save colors
+ QString capt= caption();
+ widget_flags = f;
+ clearWState( WState_Created | WState_Visible | WState_ForceHide );
+ create();
+ if ( isTopLevel() || (!parent || parent->isVisible() ) )
+ setWState( WState_ForceHide ); // new widgets do not show up in already visible parents
+
+ const QObjectList *chlist = children();
+ if ( chlist ) { // reparent children
+ QObjectList childList(*chlist);
+ QObjectListIt it(childList); // iterate over copy
+ QObject *obj;
+ while ( (obj=it.current()) ) {
+ if ( obj->isWidgetType() ) {
+ QWidget *w = (QWidget *)obj;
+ if ( !w->isTopLevel() ) {
+ XReparentWindow( x11Display(), w->winId(), winId(),
+ w->geometry().x(), w->geometry().y() );
+ } else if ( w->isPopup()
+ || w->testWFlags(WStyle_DialogBorder)
+ || w->testWFlags(WType_Dialog)
+ || w->testWFlags(WStyle_Tool) ) {
+ /*
+ when reparenting toplevel windows with toplevel-transient children,
+ we need to make sure that the window manager gets the updated
+ WM_TRANSIENT_FOR information... unfortunately, some window managers
+ don't handle changing WM_TRANSIENT_FOR before the toplevel window is
+ visible, so we unmap and remap all toplevel-transient children *after*
+ the toplevel parent has been mapped. thankfully, this is easy in Qt :)
+ */
+ XUnmapWindow(w->x11Display(), w->winId());
+ XSetTransientForHint(w->x11Display(), w->winId(), winId());
+ QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
+ }
+ }
+ ++it;
+ }
+ }
+ qPRCreate( this, old_winid );
+ if ( bgp )
+ XSetWindowBackgroundPixmap( dpy, winid, bgp->handle() );
+ else
+ XSetWindowBackground( dpy, winid, bgc.pixel(x11Screen()) );
+
+ if (isTopLevel()) {
+ // preserve maximized/fullscreen flags and the normal geometry
+ uint save_state = widget_state & (WState_Maximized | WState_FullScreen);
+ const QRect r = topData()->normalGeometry;
+ setGeometry(p.x(), p.y(), s.width(), s.height());
+ widget_state |= save_state;
+ topData()->normalGeometry = r;
+ } else {
+ setGeometry(p.x(), p.y(), s.width(), s.height());
+ }
+
+ setEnabled( enable );
+ setFocusPolicy( fp );
+ if ( !capt.isNull() ) {
+ extra->topextra->caption = QString::null;
+ setCaption( capt );
+ }
+ if ( showIt )
+ show();
+ if ( old_winid )
+ qt_XDestroyWindow( this, dpy, old_winid );
+ if ( setcurs )
+ setCursor(oldcurs);
+
+ reparentFocusWidgets( oldtlw );
+
+ // re-register dnd
+ if (oldparent)
+ oldparent->checkChildrenDnd();
+
+ if ( accept_drops )
+ setAcceptDrops( TRUE );
+ else {
+ checkChildrenDnd();
+ topData()->dnd = 0;
+ qt_dnd_enable(this, (extra && extra->children_use_dnd));
+ }
+
+ // re-enable mouse tracking
+ if (mouse_tracking)
+ setMouseTracking(mouse_tracking);
+}
+
+// Sets the EWMH (netwm) window type. Needed as a separate function
+// because create() may be too soon in some cases.
+void QWidget::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("QToolBar")) {
+ // 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 QWidget::x11SetWindowTransient( QWidget* parent )
+{
+ XSetTransientForHint( x11Display(), winId(), parent->winId());
+}
+
+/*!
+ Translates the widget coordinate \a pos to global screen
+ coordinates. For example, \c{mapToGlobal(QPoint(0,0))} would give
+ the global coordinates of the top-left pixel of the widget.
+
+ \sa mapFromGlobal() mapTo() mapToParent()
+*/
+
+QPoint QWidget::mapToGlobal( const QPoint &pos ) const
+{
+ int x, y;
+ Window child;
+ XTranslateCoordinates( x11Display(), winId(),
+ QApplication::desktop()->screen(x11Screen())->winId(),
+ pos.x(), pos.y(), &x, &y, &child );
+ return QPoint( x, y );
+}
+
+/*!
+ Translates the global screen coordinate \a pos to widget
+ coordinates.
+
+ \sa mapToGlobal() mapFrom() mapFromParent()
+*/
+
+QPoint QWidget::mapFromGlobal( const QPoint &pos ) const
+{
+ int x, y;
+ Window child;
+ XTranslateCoordinates( x11Display(),
+ QApplication::desktop()->screen(x11Screen())->winId(),
+ winId(), pos.x(), pos.y(), &x, &y, &child );
+ return QPoint( x, y );
+}
+
+/*!
+ When a widget gets focus, it should call setMicroFocusHint() with
+ some appropriate position and size, \a x, \a y, \a width and \a
+ height. This has no \e visual effect, it just provides hints to
+ any system-specific input handling tools.
+
+ The \a text argument should be TRUE if this is a position for text
+ input.
+
+ In the Windows version of Qt, this method sets the system caret,
+ which is used for user Accessibility focus handling. If \a text
+ is TRUE, it also sets the IME composition window in Far East Asian
+ language input systems.
+
+ In the X11 version of Qt, if \a text is TRUE, this method sets the
+ 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.
+
+ \sa microFocusHint()
+*/
+void QWidget::setMicroFocusHint(int x, int y, int width, int height,
+ bool text, QFont *f )
+{
+#ifndef QT_NO_IM
+ if ( text ) {
+ // trigger input context creation if it hasn't happened already
+ createInputContext();
+
+ QInputContext *qic = getInputContext();
+ if(qic) {
+ QPoint gp = mapToGlobal( QPoint( x, y ) );
+ qic->setMicroFocus(gp.x(), gp.y(), width, height, f);
+ }
+ }
+#endif
+
+ if ( QRect( x, y, width, height ) != microFocusHint() ) {
+ createExtra();
+ extraData()->micro_focus_hint.setRect( x, y, width, height );
+ }
+}
+
+
+void QWidget::setFontSys( QFont * )
+{
+ // Nothing
+}
+
+
+void QWidget::setBackgroundColorDirect( const QColor &color )
+{
+ bg_col = color;
+ if ( extra && extra->bg_pix ) { // kill the background pixmap
+ delete extra->bg_pix;
+ extra->bg_pix = 0;
+ }
+ XSetWindowBackground( x11Display(), winId(), bg_col.pixel(x11Screen()) );
+}
+
+static int allow_null_pixmaps = 0;
+
+
+void QWidget::setBackgroundPixmapDirect( const QPixmap &pixmap )
+{
+ QPixmap old;
+ if ( extra && extra->bg_pix )
+ old = *extra->bg_pix;
+ if ( !allow_null_pixmaps && pixmap.isNull() ) {
+ XSetWindowBackground( x11Display(), winId(), bg_col.pixel(x11Screen()) );
+ if ( extra && extra->bg_pix ) {
+ delete extra->bg_pix;
+ extra->bg_pix = 0;
+ }
+ } else {
+ QPixmap pm = pixmap;
+ if (!pm.isNull()) {
+ if ( pm.depth() == 1 && QPixmap::defaultDepth() > 1 ) {
+ pm = QPixmap( pixmap.size() );
+ bitBlt( &pm, 0, 0, &pixmap, 0, 0, pm.width(), pm.height() );
+ }
+ }
+ if ( extra && extra->bg_pix )
+ delete extra->bg_pix;
+ else
+ createExtra();
+ extra->bg_pix = new QPixmap( pm );
+ Q_CHECK_PTR( extra->bg_pix );
+ extra->bg_pix->x11SetScreen( x11Screen() );
+ XSetWindowBackgroundPixmap( x11Display(), winId(), extra->bg_pix->handle() );
+ if ( testWFlags(WType_Desktop) ) // save rootinfo later
+ qt_updated_rootinfo();
+ }
+}
+
+
+/*!
+ Sets the window-system background of the widget to nothing.
+
+ Note that "nothing" is actually a pixmap that isNull(), thus you
+ can check for an empty background by checking backgroundPixmap().
+
+ \sa setBackgroundPixmap(), setBackgroundColor()
+*/
+void QWidget::setBackgroundEmpty()
+{
+ allow_null_pixmaps++;
+ setErasePixmap(QPixmap());
+ allow_null_pixmaps--;
+}
+
+
+void QWidget::setBackgroundX11Relative()
+{
+ XSetWindowBackgroundPixmap( x11Display(), winId(), ParentRelative );
+}
+
+void QWidget::setCursor( const QCursor &cursor )
+{
+ if ( cursor.handle() != arrowCursor.handle()
+ || (extra && extra->curs) ) {
+ createExtra();
+ delete extra->curs;
+ extra->curs = new QCursor(cursor);
+ }
+ setWState( WState_OwnCursor );
+ qt_x11_enforce_cursor( this );
+ XFlush( x11Display() );
+}
+
+void QWidget::unsetCursor()
+{
+ if ( extra ) {
+ delete extra->curs;
+ extra->curs = 0;
+ }
+ if ( !isTopLevel() )
+ clearWState( WState_OwnCursor );
+ qt_x11_enforce_cursor( this );
+ XFlush( x11Display() );
+}
+
+static XTextProperty*
+qstring_to_xtp( const QString& s )
+{
+ static XTextProperty tp = { 0, 0, 0, 0 };
+ static bool free_prop = TRUE; // we can't free tp.value in case it references
+ // the data of the static QCString below.
+ if ( tp.value ) {
+ if ( free_prop )
+ XFree( tp.value );
+ tp.value = 0;
+ free_prop = TRUE;
+ }
+
+ static const QTextCodec* mapper = QTextCodec::codecForLocale();
+ int errCode = 0;
+ if ( mapper ) {
+ QCString mapped = mapper->fromUnicode(s);
+ char* tl[2];
+ tl[0] = mapped.data();
+ tl[1] = 0;
+ errCode = XmbTextListToTextProperty( QPaintDevice::x11AppDisplay(),
+ tl, 1, XStdICCTextStyle, &tp );
+#if defined(QT_DEBUG)
+ if ( errCode < 0 )
+ qDebug( "qstring_to_xtp result code %d", errCode );
+#endif
+ }
+ if ( !mapper || errCode < 0 ) {
+ static QCString qcs;
+ qcs = s.ascii();
+ tp.value = (uchar*)qcs.data();
+ tp.encoding = XA_STRING;
+ tp.format = 8;
+ tp.nitems = qcs.length();
+ free_prop = FALSE;
+ }
+
+ // ### If we knew WM could understand unicode, we could use
+ // ### a much simpler, cheaper encoding...
+ /*
+ tp.value = (XChar2b*)s.unicode();
+ tp.encoding = XA_UNICODE; // wish
+ tp.format = 16;
+ tp.nitems = s.length();
+ */
+
+ return &tp;
+}
+
+void QWidget::setCaption( const QString &caption )
+{
+ if ( QWidget::caption() == caption )
+ return;
+
+ topData()->caption = caption;
+ XSetWMName( x11Display(), winId(), qstring_to_xtp(caption) );
+
+ QCString net_wm_name = caption.utf8();
+ XChangeProperty(x11Display(), winId(), qt_net_wm_name, qt_utf8_string, 8,
+ PropModeReplace, (unsigned char *)net_wm_name.data(),
+ net_wm_name.length());
+
+ QEvent e( QEvent::CaptionChange );
+ QApplication::sendEvent( this, &e );
+}
+
+void QWidget::setIcon( const QPixmap &pixmap )
+{
+ if ( extra && extra->topextra ) {
+ delete extra->topextra->icon;
+ extra->topextra->icon = 0;
+ } else {
+ createTLExtra();
+ }
+ Pixmap icon_pixmap = 0;
+ Pixmap mask_pixmap = 0;
+ if ( !pixmap.isNull() ) {
+ QPixmap* pm = new QPixmap( pixmap );
+ extra->topextra->icon = pm;
+ if ( !pm->mask() )
+ pm->setMask( pm->createHeuristicMask() ); // may do detach()
+ icon_pixmap = pm->handle();
+ if ( pm->mask() )
+ mask_pixmap = pm->mask()->handle();
+ }
+ XWMHints *h = XGetWMHints( x11Display(), winId() );
+ XWMHints wm_hints;
+ bool got_hints = h != 0;
+ if ( !got_hints ) {
+ h = &wm_hints;
+ h->flags = 0;
+ }
+ h->icon_pixmap = icon_pixmap;
+ h->icon_mask = mask_pixmap;
+ h->flags |= IconPixmapHint | IconMaskHint;
+ XSetWMHints( x11Display(), winId(), h );
+ if ( got_hints )
+ XFree( (char *)h );
+ QEvent e( QEvent::IconChange );
+ QApplication::sendEvent( this, &e );
+}
+
+void QWidget::setIconText( const QString &iconText )
+{
+ if (QWidget::iconText() == iconText)
+ return;
+
+ topData()->iconText = iconText;
+ XSetWMIconName( x11Display(), winId(), qstring_to_xtp(iconText) );
+
+ QCString net_wm_icon_name = iconText.utf8();
+ XChangeProperty(x11Display(), winId(), qt_net_wm_icon_name, qt_utf8_string, 8, PropModeReplace,
+ (unsigned char *) net_wm_icon_name.data(), net_wm_icon_name.length());
+}
+
+void QWidget::setMouseTracking( bool enable )
+{
+ bool gmt = QApplication::hasGlobalMouseTracking();
+ if ( !enable == !testWState(WState_MouseTracking) && !gmt )
+ return;
+ uint m = (enable || gmt) ? (uint)PointerMotionMask : 0;
+ if ( enable )
+ setWState( WState_MouseTracking );
+ else
+ clearWState( WState_MouseTracking );
+ if ( testWFlags(WType_Desktop) ) { // desktop widget?
+ QWidget* main_desktop = find( winId() );
+ if ( main_desktop->testWFlags(WPaintDesktop) )
+ XSelectInput( x11Display(), winId(),
+ stdDesktopEventMask | ExposureMask );
+ else
+ XSelectInput( x11Display(), winId(), stdDesktopEventMask );
+ } else {
+ XSelectInput( x11Display(), winId(),
+ m | stdWidgetEventMask );
+#if defined (QT_TABLET_SUPPORT)
+ if ( devStylus != NULL ) {
+ XSelectExtensionEvent( x11Display(), winId(), event_list_stylus,
+ qt_curr_events_stylus );
+ }
+ if ( devEraser != NULL ) {
+ XSelectExtensionEvent( x11Display(), winId(), event_list_eraser,
+ qt_curr_events_eraser );
+ }
+#endif
+ }
+}
+
+
+/*!
+ Grabs the mouse input.
+
+ This widget receives all mouse events until releaseMouse() is
+ called; other widgets get no mouse events at all. Keyboard
+ events are not affected. Use grabKeyboard() if you want to grab
+ that.
+
+ \warning Bugs in mouse-grabbing applications very often lock the
+ terminal. Use this function with extreme caution, and consider
+ using the \c -nograb command line option while debugging.
+
+ It is almost never necessary to grab the mouse when using Qt, as
+ Qt grabs and releases it sensibly. In particular, Qt grabs the
+ mouse when a mouse button is pressed and keeps it until the last
+ button is released.
+
+ Note that only visible widgets can grab mouse input. If
+ isVisible() returns FALSE for a widget, that widget cannot call
+ grabMouse().
+
+ \sa releaseMouse() grabKeyboard() releaseKeyboard() grabKeyboard()
+ focusWidget()
+*/
+
+void QWidget::grabMouse()
+{
+ if ( isVisible() && !qt_nograb() ) {
+ if ( mouseGrb )
+ mouseGrb->releaseMouse();
+#if defined(QT_CHECK_STATE)
+ int status =
+#endif
+ XGrabPointer( x11Display(), winId(), False,
+ (uint)( ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | EnterWindowMask |
+ LeaveWindowMask ),
+ GrabModeAsync, GrabModeAsync,
+ None, None, qt_x_time );
+#if defined(QT_CHECK_STATE)
+ if ( status ) {
+ const char *s =
+ status == GrabNotViewable ? "\"GrabNotViewable\"" :
+ status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
+ status == GrabFrozen ? "\"GrabFrozen\"" :
+ status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
+ "<?>";
+ qWarning( "Grabbing the mouse failed with %s", s );
+ }
+#endif
+ mouseGrb = this;
+ }
+}
+
+/*!
+ \overload
+
+ Grabs the mouse input and changes the cursor shape.
+
+ The cursor will assume shape \a cursor (for as long as the mouse
+ focus is grabbed) and this widget will be the only one to receive
+ mouse events until releaseMouse() is called().
+
+ \warning Grabbing the mouse might lock the terminal.
+
+ \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
+*/
+
+void QWidget::grabMouse( const QCursor &cursor )
+{
+ if ( !qt_nograb() ) {
+ if ( mouseGrb )
+ mouseGrb->releaseMouse();
+#if defined(QT_CHECK_STATE)
+ int status =
+#endif
+ XGrabPointer( x11Display(), winId(), False,
+ (uint)(ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | EnterWindowMask | LeaveWindowMask),
+ GrabModeAsync, GrabModeAsync,
+ None, cursor.handle(), qt_x_time );
+#if defined(QT_CHECK_STATE)
+ if ( status ) {
+ const char *s =
+ status == GrabNotViewable ? "\"GrabNotViewable\"" :
+ status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
+ status == GrabFrozen ? "\"GrabFrozen\"" :
+ status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
+ "<?>";
+ qWarning( "Grabbing the mouse failed with %s", s );
+ }
+#endif
+ mouseGrb = this;
+ }
+}
+
+/*!
+ Releases the mouse grab.
+
+ \sa grabMouse(), grabKeyboard(), releaseKeyboard()
+*/
+
+void QWidget::releaseMouse()
+{
+ if ( !qt_nograb() && mouseGrb == this ) {
+ XUngrabPointer( x11Display(), qt_x_time );
+ XFlush( x11Display() );
+ mouseGrb = 0;
+ }
+}
+
+/*!
+ Grabs the keyboard input.
+
+ This widget reveives all keyboard events until releaseKeyboard()
+ is called; other widgets get no keyboard events at all. Mouse
+ events are not affected. Use grabMouse() if you want to grab that.
+
+ The focus widget is not affected, except that it doesn't receive
+ any keyboard events. setFocus() moves the focus as usual, but the
+ new focus widget receives keyboard events only after
+ releaseKeyboard() is called.
+
+ If a different widget is currently grabbing keyboard input, that
+ widget's grab is released first.
+
+ \sa releaseKeyboard() grabMouse() releaseMouse() focusWidget()
+*/
+
+void QWidget::grabKeyboard()
+{
+ if ( !qt_nograb() ) {
+ if ( keyboardGrb )
+ keyboardGrb->releaseKeyboard();
+ XGrabKeyboard( x11Display(), winid, False, GrabModeAsync, GrabModeAsync,
+ qt_x_time );
+ keyboardGrb = this;
+ }
+}
+
+/*!
+ Releases the keyboard grab.
+
+ \sa grabKeyboard(), grabMouse(), releaseMouse()
+*/
+
+void QWidget::releaseKeyboard()
+{
+ if ( !qt_nograb() && keyboardGrb == this ) {
+ XUngrabKeyboard( x11Display(), qt_x_time );
+ keyboardGrb = 0;
+ }
+}
+
+
+/*!
+ Returns the widget that is currently grabbing the mouse input.
+
+ If no widget in this application is currently grabbing the mouse,
+ 0 is returned.
+
+ \sa grabMouse(), keyboardGrabber()
+*/
+
+QWidget *QWidget::mouseGrabber()
+{
+ return mouseGrb;
+}
+
+/*!
+ Returns the widget that is currently grabbing the keyboard input.
+
+ If no widget in this application is currently grabbing the
+ keyboard, 0 is returned.
+
+ \sa grabMouse(), mouseGrabber()
+*/
+
+QWidget *QWidget::keyboardGrabber()
+{
+ return keyboardGrb;
+}
+
+/*!
+ Sets the top-level widget containing this widget to be the active
+ window.
+
+ An active window is a visible top-level window that has the
+ keyboard input focus.
+
+ This function performs the same operation as clicking the mouse on
+ the title bar of a top-level window. On X11, the result depends on
+ the Window Manager. If you want to ensure that the window is
+ stacked on top as well you should also call raise(). Note that the
+ window must be visible, otherwise setActiveWindow() has no effect.
+
+ On Windows, if you are calling this when the application is not
+ currently the active one then it will not make it the active
+ window. It will flash the task bar entry blue to indicate that
+ the window has done something. This is because Microsoft do not
+ allow an application to interrupt what the user is currently doing
+ in another application.
+
+ \sa isActiveWindow(), topLevelWidget(), show()
+*/
+
+void QWidget::setActiveWindow()
+{
+ QWidget *tlw = topLevelWidget();
+ if ( tlw->isVisible() && !tlw->topData()->embedded && !qt_deferred_map_contains(tlw) ) {
+ XSetInputFocus( x11Display(), tlw->winId(), RevertToNone, qt_x_time);
+ focusInputContext();
+ }
+}
+
+
+/*!
+ Updates the widget unless updates are disabled or the widget is
+ hidden.
+
+ This function does not cause an immediate repaint; instead it
+ schedules a paint event for processing when Qt returns to the main
+ event loop. This permits Qt to optimize for more speed and less
+ flicker than a call to repaint() does.
+
+ Calling update() several times normally results in just one
+ paintEvent() call.
+
+ Qt normally erases the widget's area before the paintEvent() call.
+ If the \c WRepaintNoErase widget flag is set, the widget is
+ responsible for painting all its pixels itself.
+
+ \sa repaint(), paintEvent(), setUpdatesEnabled(), erase(),
+ setWFlags()
+*/
+
+void QWidget::update()
+{
+ if ( (widget_state & (WState_Visible|WState_BlockUpdates)) ==
+ WState_Visible )
+ QApplication::postEvent( this, new QPaintEvent( clipRegion(), !testWFlags(WRepaintNoErase) ) );
+}
+
+/*!
+ \overload
+
+ Updates a rectangle (\a x, \a y, \a w, \a h) inside the widget
+ unless updates are disabled or the widget is hidden.
+
+ This function does not cause an immediate repaint; instead it
+ schedules a paint event for processing when Qt returns to the main
+ event loop. This permits Qt to optimize for more speed and less
+ flicker and a call to repaint() does.
+
+ Calling update() several times normally results in just one
+ paintEvent() call.
+
+ If \a w is negative, it is replaced with \c{width() - x}. If \a h
+ is negative, it is replaced width \c{height() - y}.
+
+ Qt normally erases the specified area before the paintEvent()
+ call. If the \c WRepaintNoErase widget flag is set, the widget is
+ responsible for painting all its pixels itself.
+
+ \sa repaint(), paintEvent(), setUpdatesEnabled(), erase()
+*/
+
+void QWidget::update( int x, int y, int w, int h )
+{
+ if ( w && h &&
+ (widget_state & (WState_Visible|WState_BlockUpdates)) == WState_Visible ) {
+ if ( w < 0 )
+ w = crect.width() - x;
+ if ( h < 0 )
+ h = crect.height() - y;
+ if ( w != 0 && h != 0 )
+ QApplication::postEvent( this,
+ new QPaintEvent( clipRegion().intersect(QRect(x,y,w,h)),
+ !testWFlags( WRepaintNoErase ) ) );
+ }
+}
+
+/*!
+ \overload void QWidget::update( const QRect &r )
+
+ Updates a rectangle \a r inside the widget unless updates are
+ disabled or the widget is hidden.
+
+ This function does not cause an immediate repaint; instead it
+ schedules a paint event for processing when Qt returns to the main
+ event loop. This permits Qt to optimize for more speed and less
+ flicker and a call to repaint() does.
+
+ Calling update() several times normally results in just one
+ paintEvent() call.
+*/
+
+/*!
+ \overload void QWidget::repaint( bool erase )
+
+ This version repaints the entire widget.
+*/
+
+/*!
+ \overload void QWidget::repaint()
+
+ This version erases and repaints the entire widget.
+*/
+
+/*!
+ Repaints the widget directly by calling paintEvent() immediately,
+ unless updates are disabled or the widget is hidden.
+
+ If \a erase is TRUE, Qt erases the area \a (x, y, w, h) before the
+ paintEvent() call.
+
+ If \a w is negative, it is replaced with \c{width() - x}, and if
+ \a h is negative, it is replaced width \c{height() - y}.
+
+ We suggest only using repaint() if you need an immediate repaint,
+ for example during animation. In almost all circumstances update()
+ is better, as it permits Qt to optimize for speed and minimize
+ flicker.
+
+ \warning If you call repaint() in a function which may itself be
+ called from paintEvent(), you may get infinite recursion. The
+ update() function never causes recursion.
+
+ \sa update(), paintEvent(), setUpdatesEnabled(), erase()
+*/
+
+void QWidget::repaint( int x, int y, int w, int h, bool erase )
+{
+ if ( (widget_state & (WState_Visible|WState_BlockUpdates)) == WState_Visible ) {
+ if ( x > crect.width() || y > crect.height() )
+ return;
+ if ( w < 0 )
+ w = crect.width() - x;
+ if ( h < 0 )
+ h = crect.height() - y;
+ QRect r(x,y,w,h);
+ if ( r.isEmpty() )
+ return; // nothing to do
+ QPaintEvent e( r, erase );
+ if ( r != rect() )
+ qt_set_paintevent_clipping( this, r );
+ if ( erase && w != 0 && h != 0 ) {
+ if ( backgroundOrigin() == WidgetOrigin )
+ XClearArea( x11Display(), winId(), x, y, w, h, False );
+ else
+ this->erase( x, y, w, h);
+ }
+ QApplication::sendEvent( this, &e );
+ qt_clear_paintevent_clipping();
+ }
+}
+
+/*!
+ \overload
+
+ Repaints the widget directly by calling paintEvent() directly,
+ unless updates are disabled or the widget is hidden.
+
+ Erases the widget region \a reg if \a erase is TRUE.
+
+ Only use repaint if your widget needs to be repainted immediately,
+ for example when doing some animation. In all other cases, use
+ update(). Calling update() many times in a row will generate a
+ single paint event.
+
+ \warning If you call repaint() in a function which may itself be
+ called from paintEvent(), you may get infinite recursion. The
+ update() function never causes recursion.
+
+ \sa update(), paintEvent(), setUpdatesEnabled(), erase()
+*/
+
+void QWidget::repaint( const QRegion& reg, bool erase )
+{
+ if ( (widget_state & (WState_Visible|WState_BlockUpdates)) == WState_Visible ) {
+ QPaintEvent e( reg, erase );
+ qt_set_paintevent_clipping( this, reg );
+ if ( erase )
+ this->erase(reg);
+ QApplication::sendEvent( this, &e );
+ qt_clear_paintevent_clipping();
+ }
+}
+
+/*!
+ \overload void QWidget::repaint( const QRect &r, bool erase )
+
+ Repaints the widget directly by calling paintEvent() directly,
+ unless updates are disabled or the widget is hidden.
+
+ Erases the widget region \a r if \a erase is TRUE.
+*/
+
+void QWidget::setWindowState(uint newstate)
+{
+ bool needShow = FALSE;
+ uint oldstate = windowState();
+ if (isTopLevel()) {
+ QTLWExtra *top = topData();
+
+ if ((oldstate & WindowMaximized) != (newstate & WindowMaximized)) {
+ if (qt_net_supports(qt_net_wm_state_max_h) && qt_net_supports(qt_net_wm_state_max_v)) {
+ qt_net_change_wm_state(this, (newstate & WindowMaximized),
+ qt_net_wm_state_max_h, qt_net_wm_state_max_v);
+ } else if (! (newstate & WindowFullScreen)) {
+ if (newstate & WindowMaximized) {
+ // save original geometry
+ const QRect normalGeometry = geometry();
+
+ if (isVisible()) {
+ updateFrameStrut();
+ const QRect maxRect = QApplication::desktop()->availableGeometry(this);
+ const QRect r = top->normalGeometry;
+ setGeometry(maxRect.x() + top->fleft,
+ maxRect.y() + top->ftop,
+ maxRect.width() - top->fleft - top->fright,
+ maxRect.height() - top->ftop - top->fbottom);
+ top->normalGeometry = r;
+ }
+
+ if (top->normalGeometry.width() < 0)
+ top->normalGeometry = normalGeometry;
+ } else {
+ // restore original geometry
+ setGeometry(top->normalGeometry);
+ }
+ }
+ }
+
+ if ((oldstate & WindowFullScreen) != (newstate & WindowFullScreen)) {
+ if (qt_net_supports(qt_net_wm_state_fullscreen)) {
+ qt_net_change_wm_state(this, (newstate & WindowFullScreen),
+ qt_net_wm_state_fullscreen);
+ } else {
+ needShow = isVisible();
+
+ if (newstate & WindowFullScreen) {
+ const QRect normalGeometry = QRect(pos(), size());
+
+ top->savedFlags = getWFlags();
+ reparent(0, WType_TopLevel | WStyle_Customize | WStyle_NoBorder |
+ // preserve some widget flags
+ (getWFlags() & 0xffff0000),
+ mapToGlobal(QPoint(0, 0)));
+ const QRect r = top->normalGeometry;
+ setGeometry(qApp->desktop()->screenGeometry(this));
+ top->normalGeometry = r;
+
+ if ( top->normalGeometry.width() < 0 )
+ top->normalGeometry = normalGeometry;
+ } else {
+ reparent( 0, top->savedFlags, mapToGlobal(QPoint(0, 0)) );
+
+ if (newstate & WindowMaximized) {
+ // from fullscreen to maximized
+ updateFrameStrut();
+ const QRect maxRect = QApplication::desktop()->availableGeometry(this);
+ const QRect r = top->normalGeometry;
+ setGeometry(maxRect.x() + top->fleft,
+ maxRect.y() + top->ftop,
+ maxRect.width() - top->fleft - top->fright,
+ maxRect.height() - top->ftop - top->fbottom);
+ top->normalGeometry = r;
+ } else {
+ // restore original geometry
+ setGeometry(top->normalGeometry);
+ }
+ }
+ }
+ }
+
+ if ((oldstate & WindowMinimized) != (newstate & WindowMinimized)) {
+ if (isVisible()) {
+ if (newstate & WindowMinimized) {
+ XEvent e;
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = qt_wm_change_state;
+ e.xclient.display = x11Display();
+ e.xclient.window = winid;
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = IconicState;
+ e.xclient.data.l[1] = 0;
+ e.xclient.data.l[2] = 0;
+ e.xclient.data.l[3] = 0;
+ e.xclient.data.l[4] = 0;
+ XSendEvent(x11Display(), RootWindow(x11Display(), x11Screen()),
+ False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
+ } else {
+ XMapWindow(x11Display(), winId());
+ }
+ }
+
+ needShow = FALSE;
+ }
+ }
+
+ widget_state &= ~(WState_Minimized | WState_Maximized | WState_FullScreen);
+ if (newstate & WindowMinimized)
+ widget_state |= WState_Minimized;
+ if (newstate & WindowMaximized)
+ widget_state |= WState_Maximized;
+ if (newstate & WindowFullScreen)
+ widget_state |= WState_FullScreen;
+
+ if (needShow)
+ show();
+
+ if (newstate & WindowActive)
+ setActiveWindow();
+
+ QEvent e(QEvent::WindowStateChange);
+ QApplication::sendEvent(this, &e);
+}
+
+/*!
+ \internal
+ Platform-specific part of QWidget::show().
+*/
+
+void QWidget::showWindow()
+{
+ if ( isTopLevel() ) {
+ XWMHints *h = XGetWMHints( x11Display(), winId() );
+ XWMHints wm_hints;
+ bool got_hints = h != 0;
+ if ( !got_hints ) {
+ h = &wm_hints;
+ h->flags = 0;
+ }
+ h->initial_state = testWState(WState_Minimized) ? IconicState : NormalState;
+ h->flags |= StateHint;
+ XSetWMHints( x11Display(), winId(), h );
+ if ( got_hints )
+ XFree( (char *)h );
+
+ if (qt_x_user_time != CurrentTime) {
+ XChangeProperty(x11Display(), winId(), qt_net_wm_user_time, XA_CARDINAL,
+ 32, PropModeReplace, (unsigned char *) &qt_x_user_time, 1);
+ }
+
+ if (!topData()->embedded &&
+ topData()->parentWinId &&
+ topData()->parentWinId != QPaintDevice::x11AppRootWindow(x11Screen()) &&
+ !isMinimized() ) {
+ qt_deferred_map_add( this );
+ return;
+ }
+
+ if (isMaximized() && !isFullScreen()
+ && !(qt_net_supports(qt_net_wm_state_max_h)
+ && qt_net_supports(qt_net_wm_state_max_v))) {
+ XMapWindow( x11Display(), winId() );
+ qt_wait_for_window_manager(this);
+
+ // if the wm was not smart enough to adjust our size, do that manually
+ updateFrameStrut();
+ QRect maxRect = QApplication::desktop()->availableGeometry(this);
+
+ QTLWExtra *top = topData();
+ QRect normalRect = top->normalGeometry;
+
+ setGeometry(maxRect.x() + top->fleft,
+ maxRect.y() + top->ftop,
+ maxRect.width() - top->fleft - top->fright,
+ maxRect.height() - top->ftop - top->fbottom);
+
+ // restore the original normalGeometry
+ top->normalGeometry = normalRect;
+ // internalSetGeometry() clears the maximized flag... make sure we set it back
+ setWState(WState_Maximized);
+
+ return;
+ }
+
+ if (isFullScreen() && !qt_net_supports(qt_net_wm_state_fullscreen)) {
+ XMapWindow(x11Display(), winId());
+ qt_wait_for_window_manager(this);
+ return;
+ }
+ }
+ XMapWindow( x11Display(), winId() );
+}
+
+
+/*!
+ \internal
+ Platform-specific part of QWidget::hide().
+*/
+
+void QWidget::hideWindow()
+{
+ clearWState( WState_Exposed );
+ deactivateWidgetCleanup();
+ if ( isTopLevel() ) {
+ qt_deferred_map_take( this );
+ if ( winId() ) // in nsplugin, may be 0
+ XWithdrawWindow( x11Display(), winId(), x11Screen() );
+
+ QTLWExtra *top = topData();
+ crect.moveTopLeft( QPoint(crect.x() - top->fleft, crect.y() - top->ftop ) );
+
+ // zero the frame strut and mark it dirty
+ top->fleft = top->fright = top->ftop = top->fbottom = 0;
+ fstrut_dirty = TRUE;
+
+ XFlush( x11Display() );
+ } else {
+ if ( winId() ) // in nsplugin, may be 0
+ XUnmapWindow( x11Display(), winId() );
+ }
+}
+
+/*!
+ Raises this widget to the top of the parent widget's stack.
+
+ After this call the widget will be visually in front of any
+ overlapping sibling widgets.
+
+ \sa lower(), stackUnder()
+*/
+
+void QWidget::raise()
+{
+ QWidget *p = parentWidget();
+ if ( p && p->childObjects && p->childObjects->findRef(this) >= 0 )
+ p->childObjects->append( p->childObjects->take() );
+ XRaiseWindow( x11Display(), winId() );
+}
+
+/*!
+ Lowers the widget to the bottom of the parent widget's stack.
+
+ After this call the widget will be visually behind (and therefore
+ obscured by) any overlapping sibling widgets.
+
+ \sa raise(), stackUnder()
+*/
+
+void QWidget::lower()
+{
+ QWidget *p = parentWidget();
+ if ( p && p->childObjects && p->childObjects->findRef(this) >= 0 )
+ p->childObjects->insert( 0, p->childObjects->take() );
+ XLowerWindow( x11Display(), winId() );
+}
+
+
+/*!
+ Places the widget under \a w in the parent widget's stack.
+
+ To make this work, the widget itself and \a w must be siblings.
+
+ \sa raise(), lower()
+*/
+void QWidget::stackUnder( QWidget* w)
+{
+ QWidget *p = parentWidget();
+ if ( !w || isTopLevel() || p != w->parentWidget() || this == w )
+ return;
+ if ( p && p->childObjects && p->childObjects->findRef(w) >= 0 && p->childObjects->findRef(this) >= 0 ) {
+ p->childObjects->take();
+ p->childObjects->insert( p->childObjects->findRef(w), this );
+ }
+ Window stack[2];
+ stack[0] = w->winId();;
+ stack[1] = winId();
+ XRestackWindows( x11Display(), stack, 2 );
+}
+
+
+
+/*
+ The global variable qt_widget_tlw_gravity defines the window gravity of
+ the next top level window to be created. We do this when setting the
+ main widget's geometry and the "-geometry" command line option contains
+ a negative position.
+*/
+
+int qt_widget_tlw_gravity = NorthWestGravity;
+
+static void do_size_hints( QWidget* widget, QWExtra *x )
+{
+ XSizeHints s;
+ s.flags = 0;
+ if ( x ) {
+ s.x = widget->x();
+ s.y = widget->y();
+ s.width = widget->width();
+ s.height = widget->height();
+ if ( x->minw > 0 || x->minh > 0 ) { // add minimum size hints
+ s.flags |= PMinSize;
+ s.min_width = x->minw;
+ s.min_height = x->minh;
+ }
+ if ( x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX ) {
+ s.flags |= PMaxSize; // add maximum size hints
+ s.max_width = x->maxw;
+ s.max_height = x->maxh;
+ }
+ if ( x->topextra &&
+ (x->topextra->incw > 0 || x->topextra->inch > 0) )
+ { // add resize increment hints
+ s.flags |= PResizeInc | PBaseSize;
+ s.width_inc = x->topextra->incw;
+ s.height_inc = x->topextra->inch;
+ s.base_width = x->topextra->basew;
+ s.base_height = x->topextra->baseh;
+ }
+
+ if ( x->topextra && x->topextra->uspos) {
+ s.flags |= USPosition;
+ s.flags |= PPosition;
+ }
+ if ( x->topextra && x->topextra->ussize) {
+ s.flags |= USSize;
+ s.flags |= PSize;
+ }
+ }
+ s.flags |= PWinGravity;
+ s.win_gravity = qt_widget_tlw_gravity; // usually NorthWest
+ // reset in case it was set
+ qt_widget_tlw_gravity =
+ QApplication::reverseLayout() ? NorthEastGravity : NorthWestGravity;
+ XSetWMNormalHints( widget->x11Display(), widget->winId(), &s );
+}
+
+
+void QWidget::internalSetGeometry( int x, int y, int w, int h, bool isMove )
+{
+ Display *dpy = x11Display();
+
+ if ( testWFlags(WType_Desktop) )
+ return;
+ if (isTopLevel()) {
+ if (!qt_net_supports(qt_net_wm_state_max_h)
+ && !qt_net_supports(qt_net_wm_state_max_v))
+ clearWState(WState_Maximized);
+ if (!qt_net_supports(qt_net_wm_state_fullscreen))
+ clearWState(WState_FullScreen);
+ topData()->normalGeometry = QRect(0, 0, -1, -1);
+ } else {
+ // for QWorkspace
+ clearWState(WState_Maximized);
+ clearWState(WState_FullScreen);
+ }
+ if ( extra ) { // any size restrictions?
+ w = QMIN(w,extra->maxw);
+ h = QMIN(h,extra->maxh);
+ w = QMAX(w,extra->minw);
+ h = QMAX(h,extra->minh);
+ }
+ if ( w < 1 ) // invalid size
+ w = 1;
+ if ( h < 1 )
+ h = 1;
+ QPoint oldPos( pos() );
+ QSize oldSize( size() );
+ QRect oldGeom( crect );
+ QRect r( x, y, w, h );
+
+ // We only care about stuff that changes the geometry, or may
+ // cause the window manager to change its state
+ if ( !isTopLevel() && oldGeom == r )
+ return;
+
+ crect = r;
+ bool isResize = size() != oldSize;
+
+ if ( isTopLevel() ) {
+ if ( isMove )
+ topData()->uspos = 1;
+ if ( isResize )
+ topData()->ussize = 1;
+ do_size_hints( this, extra );
+ }
+
+ if ( isMove ) {
+ if (! qt_broken_wm)
+ // pos() is right according to ICCCM 4.1.5
+ XMoveResizeWindow( dpy, winid, pos().x(), pos().y(), w, h );
+ else
+ // work around 4Dwm's incompliance with ICCCM 4.1.5
+ XMoveResizeWindow( dpy, winid, x, y, w, h );
+ } else if ( isResize )
+ XResizeWindow( dpy, winid, w, h );
+
+ if ( isVisible() ) {
+ if ( isMove && pos() != oldPos ) {
+ if ( ! qt_broken_wm ) {
+ // pos() is right according to ICCCM 4.1.5
+ QMoveEvent e( pos(), oldPos );
+ QApplication::sendEvent( this, &e );
+ } else {
+ // work around 4Dwm's incompliance with ICCCM 4.1.5
+ QMoveEvent e( crect.topLeft(), oldGeom.topLeft() );
+ QApplication::sendEvent( this, &e );
+ }
+ }
+ if ( isResize ) {
+
+ // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
+ setWState( WState_ConfigPending );
+
+ QResizeEvent e( size(), oldSize );
+ QApplication::sendEvent( this, &e );
+ }
+ } else {
+ if ( isMove && pos() != oldPos ) {
+ if ( ! qt_broken_wm )
+ // pos() is right according to ICCCM 4.1.5
+ QApplication::postEvent( this, new QMoveEvent( pos(), oldPos ) );
+ else
+ // work around 4Dwm's incompliance with ICCCM 4.1.5
+ QApplication::postEvent( this, new QMoveEvent( crect.topLeft(),
+ oldGeom.topLeft() ) );
+ }
+ if ( isResize )
+ QApplication::postEvent( this,
+ new QResizeEvent( size(), oldSize ) );
+ }
+}
+
+
+/*!
+ \overload
+
+ This function corresponds to setMinimumSize( QSize(minw, minh) ).
+ Sets the minimum width to \a minw and the minimum height to \a
+ minh.
+*/
+
+void QWidget::setMinimumSize( int minw, int minh )
+{
+#if defined(QT_CHECK_RANGE)
+ if ( minw < 0 || minh < 0 )
+ qWarning("QWidget::setMinimumSize: The smallest allowed size is (0,0)");
+#endif
+ createExtra();
+ if ( extra->minw == minw && extra->minh == minh )
+ return;
+ extra->minw = minw;
+ extra->minh = minh;
+ if ( minw > width() || minh > height() ) {
+ bool resized = testWState( WState_Resized );
+ resize( QMAX(minw,width()), QMAX(minh,height()) );
+ if ( !resized )
+ clearWState( WState_Resized ); // not a user resize
+ }
+ if ( testWFlags(WType_TopLevel) )
+ do_size_hints( this, extra );
+ updateGeometry();
+}
+
+/*!
+ \overload
+
+ This function corresponds to setMaximumSize( QSize(\a maxw, \a
+ maxh) ). Sets the maximum width to \a maxw and the maximum height
+ to \a maxh.
+*/
+void QWidget::setMaximumSize( int maxw, int maxh )
+{
+#if defined(QT_CHECK_RANGE)
+ if ( maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX ) {
+ qWarning("QWidget::setMaximumSize: (%s/%s) "
+ "The largest allowed size is (%d,%d)",
+ name( "unnamed" ), className(), QWIDGETSIZE_MAX,
+ QWIDGETSIZE_MAX );
+ maxw = QMIN( maxw, QWIDGETSIZE_MAX );
+ maxh = QMIN( maxh, QWIDGETSIZE_MAX );
+ }
+ if ( maxw < 0 || maxh < 0 ) {
+ qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
+ "are not possible",
+ name( "unnamed" ), className(), maxw, maxh );
+ maxw = QMAX( maxw, 0 );
+ maxh = QMAX( maxh, 0 );
+ }
+#endif
+ createExtra();
+ if ( extra->maxw == maxw && extra->maxh == maxh )
+ return;
+ extra->maxw = maxw;
+ extra->maxh = maxh;
+ if ( maxw < width() || maxh < height() ) {
+ bool resized = testWState( WState_Resized );
+ resize( QMIN(maxw,width()), QMIN(maxh,height()) );
+ if ( !resized )
+ clearWState( WState_Resized ); // not a user resize
+ }
+ if ( testWFlags(WType_TopLevel) )
+ do_size_hints( this, extra );
+ updateGeometry();
+}
+
+/*!
+ \overload
+
+ Sets the x (width) size increment to \a w and the y (height) size
+ increment to \a h.
+*/
+void QWidget::setSizeIncrement( int w, int h )
+{
+ QTLWExtra* x = topData();
+ if ( x->incw == w && x->inch == h )
+ return;
+ x->incw = w;
+ x->inch = h;
+ if ( testWFlags(WType_TopLevel) )
+ do_size_hints( this, extra );
+}
+
+/*!
+ \overload
+
+ This corresponds to setBaseSize( QSize(\a basew, \a baseh) ). Sets
+ the widgets base size to width \a basew and height \a baseh.
+*/
+void QWidget::setBaseSize( int basew, int baseh )
+{
+ createTLExtra();
+ QTLWExtra* x = topData();
+ if ( x->basew == basew && x->baseh == baseh )
+ return;
+ x->basew = basew;
+ x->baseh = baseh;
+ if ( testWFlags(WType_TopLevel) )
+ do_size_hints( this, extra );
+}
+
+/*!
+ \overload void QWidget::erase()
+
+ This version erases the entire widget.
+*/
+
+/*!
+ \overload void QWidget::erase( const QRect &r )
+
+ Erases the specified area \a r in the widget without generating a
+ \link paintEvent() paint event\endlink.
+*/
+
+/*!
+ Erases the specified area \a (x, y, w, h) in the widget without
+ generating a \link paintEvent() paint event\endlink.
+
+ If \a w is negative, it is replaced with \c{width() - x}. If \a h
+ is negative, it is replaced width \c{height() - y}.
+
+ Child widgets are not affected.
+
+ \sa repaint()
+*/
+
+void QWidget::erase( int x, int y, int w, int h )
+{
+ extern void qt_erase_rect( QWidget*, const QRect& ); // in qpainer_x11.cpp
+ if ( w < 0 )
+ w = crect.width() - x;
+ if ( h < 0 )
+ h = crect.height() - y;
+ if ( w != 0 && h != 0 )
+ qt_erase_rect( this, QRect(x, y, w, h ) );
+}
+
+/*!
+ \overload
+
+ Erases the area defined by \a reg, without generating a \link
+ paintEvent() paint event\endlink.
+
+ Child widgets are not affected.
+*/
+
+void QWidget::erase( const QRegion& reg )
+{
+ extern void qt_erase_region( QWidget*, const QRegion& ); // in qpainer_x11.cpp
+ qt_erase_region( this, reg );
+}
+
+/*!
+ Scrolls the widget including its children \a dx pixels to the
+ right and \a dy downwards. Both \a dx and \a dy may be negative.
+
+ After scrolling, scroll() sends a paint event for the the part
+ that is read but not written. For example, when scrolling 10
+ pixels rightwards, the leftmost ten pixels of the widget need
+ repainting. The paint event may be delivered immediately or later,
+ depending on some heuristics (note that you might have to force
+ processing of paint events using QApplication::sendPostedEvents()
+ when using scroll() and move() in combination).
+
+ \sa QScrollView erase() bitBlt()
+*/
+
+void QWidget::scroll( int dx, int dy )
+{
+ scroll( dx, dy, QRect() );
+}
+
+/*!
+ \overload
+
+ This version only scrolls \a r and does not move the children of
+ the widget.
+
+ If \a r is empty or invalid, the result is undefined.
+
+ \sa QScrollView erase() bitBlt()
+*/
+void QWidget::scroll( int dx, int dy, const QRect& r )
+{
+ if ( testWState( WState_BlockUpdates ) && !children() )
+ return;
+ bool valid_rect = r.isValid();
+ bool just_update = QABS( dx ) > width() || QABS( dy ) > height();
+ if ( just_update )
+ update();
+ QRect sr = valid_rect?r:clipRegion().boundingRect();
+ int x1, y1, x2, y2, w=sr.width(), h=sr.height();
+ if ( dx > 0 ) {
+ x1 = sr.x();
+ x2 = x1+dx;
+ w -= dx;
+ } else {
+ x2 = sr.x();
+ x1 = x2-dx;
+ w += dx;
+ }
+ if ( dy > 0 ) {
+ y1 = sr.y();
+ y2 = y1+dy;
+ h -= dy;
+ } else {
+ y2 = sr.y();
+ y1 = y2-dy;
+ h += dy;
+ }
+
+ if ( dx == 0 && dy == 0 )
+ return;
+
+ Display *dpy = x11Display();
+ GC gc = qt_xget_readonly_gc( x11Screen(), FALSE );
+ // Want expose events
+ if ( w > 0 && h > 0 && !just_update ) {
+ XSetGraphicsExposures( dpy, gc, True );
+ XCopyArea( dpy, winId(), winId(), gc, x1, y1, w, h, x2, y2);
+ XSetGraphicsExposures( dpy, gc, False );
+ }
+
+ if ( !valid_rect && children() ) { // scroll children
+ QPoint pd( dx, dy );
+ QObjectListIt it(*children());
+ register QObject *object;
+ while ( it ) { // move all children
+ object = it.current();
+ if ( object->isWidgetType() ) {
+ QWidget *w = (QWidget *)object;
+ w->move( w->pos() + pd );
+ }
+ ++it;
+ }
+ }
+
+ if ( just_update )
+ return;
+
+ // Don't let the server be bogged-down with repaint events
+ bool repaint_immediately = qt_sip_count( this ) < 3;
+
+ if ( dx ) {
+ int x = x2 == sr.x() ? sr.x()+w : sr.x();
+ if ( repaint_immediately )
+ repaint( x, sr.y(), QABS(dx), sr.height(), !testWFlags(WRepaintNoErase) );
+ else
+ XClearArea( dpy, winid, x, sr.y(), QABS(dx), sr.height(), True );
+ }
+ if ( dy ) {
+ int y = y2 == sr.y() ? sr.y()+h : sr.y();
+ if ( repaint_immediately )
+ repaint( sr.x(), y, sr.width(), QABS(dy), !testWFlags(WRepaintNoErase) );
+ else
+ XClearArea( dpy, winid, sr.x(), y, sr.width(), QABS(dy), True );
+ }
+
+ qt_insert_sip( this, dx, dy ); // #### ignores r
+}
+
+
+/*!
+ \overload void QWidget::drawText( const QPoint &pos, const QString& str )
+
+ Draws the string \a str at position \a pos.
+*/
+
+/*!
+ Draws the string \a str at position \a(x, y).
+
+ The \a y position is the base line position of the text. The text
+ is drawn using the default font and the default foreground color.
+
+ This function is provided for convenience. You will generally get
+ more flexible results and often higher speed by using a a \link
+ QPainter painter\endlink instead.
+
+ \sa setFont(), foregroundColor(), QPainter::drawText()
+*/
+
+void QWidget::drawText( int x, int y, const QString &str )
+{
+ if ( testWState(WState_Visible) ) {
+ QPainter paint;
+ paint.begin( this );
+ paint.drawText( x, y, str );
+ paint.end();
+ }
+}
+
+
+/*!
+ Internal implementation of the virtual QPaintDevice::metric()
+ function.
+
+ Use the QPaintDeviceMetrics class instead.
+
+ \a m is the metric to get.
+*/
+
+int QWidget::metric( int m ) const
+{
+ int val;
+ if ( m == QPaintDeviceMetrics::PdmWidth ) {
+ val = crect.width();
+ } else if ( m == QPaintDeviceMetrics::PdmHeight ) {
+ val = crect.height();
+ } else {
+ Display *dpy = x11Display();
+ int scr = x11Screen();
+ switch ( m ) {
+ case QPaintDeviceMetrics::PdmDpiX:
+ case QPaintDeviceMetrics::PdmPhysicalDpiX:
+ val = QPaintDevice::x11AppDpiX( scr );
+ break;
+ case QPaintDeviceMetrics::PdmDpiY:
+ case QPaintDeviceMetrics::PdmPhysicalDpiY:
+ val = QPaintDevice::x11AppDpiY( scr );
+ break;
+ case QPaintDeviceMetrics::PdmWidthMM:
+ val = (DisplayWidthMM(dpy,scr)*crect.width())/
+ DisplayWidth(dpy,scr);
+ break;
+ case QPaintDeviceMetrics::PdmHeightMM:
+ val = (DisplayHeightMM(dpy,scr)*crect.height())/
+ DisplayHeight(dpy,scr);
+ break;
+ case QPaintDeviceMetrics::PdmNumColors:
+ val = x11Cells();
+ break;
+ case QPaintDeviceMetrics::PdmDepth:
+ val = x11Depth();
+ break;
+ default:
+ val = 0;
+#if defined(QT_CHECK_RANGE)
+ qWarning( "QWidget::metric: Invalid metric command" );
+#endif
+ }
+ }
+ return val;
+}
+
+void QWidget::createSysExtra()
+{
+ extra->xDndProxy = 0;
+ extra->children_use_dnd = FALSE;
+ extra->compress_events = TRUE;
+}
+
+void QWidget::deleteSysExtra()
+{
+}
+
+void QWidget::createTLSysExtra()
+{
+#if defined(QT_NO_IM_EXTENSIONS)
+ // created lazily
+ extra->topextra->xic = 0;
+#endif
+#ifndef QT_NO_XSYNC
+ extra->topextra->syncCounter = 0;
+ extra->topextra->syncRequestValue[0] = 0;
+ extra->topextra->syncRequestValue[1] = 0;
+#endif
+}
+
+void QWidget::deleteTLSysExtra()
+{
+ // don't destroy input context here. it will be destroyed in
+ // QWidget::destroy() destroyInputContext();
+}
+
+/*
+ examine the children of our parent up the tree and set the
+ children_use_dnd extra data appropriately... this is used to keep DND enabled
+ for widgets that are reparented and don't have DND enabled, BUT *DO* have
+ children (or children of children ...) with DND enabled...
+*/
+void QWidget::checkChildrenDnd()
+{
+ QWidget *widget = this;
+ const QObjectList *children;
+ const QObject *object;
+ const QWidget *child;
+ while (widget && ! widget->isDesktop()) {
+ // note: this isn't done for the desktop widget
+
+ bool children_use_dnd = FALSE;
+ children = widget->children();
+ if ( children ) {
+ QObjectListIt it(*children);
+ while ( (object = it.current()) ) {
+ ++it;
+ if ( object->isWidgetType() ) {
+ child = (const QWidget *) object;
+ children_use_dnd = (children_use_dnd ||
+ child->acceptDrops() ||
+ (child->extra &&
+ child->extra->children_use_dnd));
+ }
+ }
+ }
+
+ widget->createExtra();
+ widget->extra->children_use_dnd = children_use_dnd;
+
+ widget = widget->parentWidget();
+ }
+}
+
+
+#ifndef QT_NO_XSYNC
+// create a window's XSyncCounter
+void QWidget::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 QWidget::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 QWidget::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 QWidget::handleSyncRequest( void* ev )
+{
+ XEvent* xev = (XEvent*)ev;
+ topData()->syncRequestValue[ 0 ] = xev->xclient.data.l[ 2 ];
+ topData()->syncRequestValue[ 1 ] = xev->xclient.data.l[ 3 ];
+}
+#endif // QT_NO_XSYNC
+
+
+/*!
+ \property QWidget::acceptDrops
+ \brief whether drop events are enabled for this widget
+
+ Setting this property to TRUE announces to the system that this
+ widget \e may be able to accept drop events.
+
+ If the widget is the desktop (QWidget::isDesktop()), this may
+ fail if another application is using the desktop; you can call
+ acceptDrops() to test if this occurs.
+
+ \warning
+ Do not modify this property in a Drag&Drop event handler.
+*/
+bool QWidget::acceptDrops() const
+{
+ return testWState( WState_DND );
+}
+
+void QWidget::setAcceptDrops( bool on )
+{
+ if ( testWState(WState_DND) != on ) {
+ if ( qt_dnd_enable( this, on ) ) {
+ if ( on )
+ setWState( WState_DND );
+ else
+ clearWState( WState_DND );
+ }
+
+ checkChildrenDnd();
+ }
+}
+
+/*!
+ \overload
+
+ Causes only the parts of the widget which overlap \a region to be
+ visible. If the region includes pixels outside the rect() of the
+ widget, window system controls in that area may or may not be
+ visible, depending on the platform.
+
+ Note that this effect can be slow if the region is particularly
+ complex.
+
+ \sa setMask(), clearMask()
+*/
+
+void QWidget::setMask( const QRegion& region )
+{
+ XShapeCombineRegion( x11Display(), winId(), ShapeBounding, 0, 0,
+ region.handle(), ShapeSet );
+}
+
+/*!
+ Causes only the pixels of the widget for which \a bitmap has a
+ corresponding 1 bit to be visible. Use Qt::color0 to draw
+ transparent regions and Qt::color1 to draw opaque regions of the
+ bitmap.
+
+ If the region includes pixels outside the rect() of the widget,
+ window system controls in that area may or may not be visible,
+ depending on the platform.
+
+ Note that this effect can be slow if the region is particularly
+ complex.
+
+ See \c examples/tux for an example of masking for transparency.
+
+ \sa setMask(), clearMask()
+*/
+
+void QWidget::setMask( const QBitmap &bitmap )
+{
+ QBitmap bm = bitmap;
+ if ( bm.x11Screen() != x11Screen() )
+ bm.x11SetScreen( x11Screen() );
+ XShapeCombineMask( x11Display(), winId(), ShapeBounding, 0, 0,
+ bm.handle(), ShapeSet );
+}
+
+/*!
+ Removes any mask set by setMask().
+
+ \sa setMask()
+*/
+
+void QWidget::clearMask()
+{
+ XShapeCombineMask( x11Display(), winId(), ShapeBounding, 0, 0,
+ None, ShapeSet );
+}
+
+/*!\reimp
+ */
+void QWidget::setName( const char *name )
+{
+ QObject::setName( name );
+ if ( isTopLevel() ) {
+ XChangeProperty( x11Display(), winId(),
+ qt_window_role, XA_STRING, 8, PropModeReplace,
+ (unsigned char *)name, qstrlen( name ) );
+ }
+}
+
+
+/*!
+ \internal
+
+ Computes the frame rectangle when needed. This is an internal function, you
+ should never call this.
+*/
+
+void QWidget::updateFrameStrut() const
+{
+ QWidget *that = (QWidget *) this;
+
+ if (! isVisible() || isDesktop()) {
+ that->fstrut_dirty = (! isVisible());
+ return;
+ }
+
+ Atom type_ret;
+ Window l = winId(), w = winId(), p, r; // target window, it's parent, root
+ Window *c;
+ int i_unused;
+ unsigned int nc;
+ unsigned char *data_ret;
+ unsigned long l_unused;
+
+ while (XQueryTree(QPaintDevice::x11AppDisplay(), w, &r, &p, &c, &nc)) {
+ if (c && nc > 0)
+ XFree(c);
+
+ if (! p) {
+ qWarning("QWidget::updateFrameStrut(): ERROR - no parent");
+ return;
+ }
+
+ // if the parent window is the root window, an Enlightenment virtual root or
+ // a NET WM virtual root window, stop here
+ data_ret = 0;
+ if (p == r ||
+ (XGetWindowProperty(QPaintDevice::x11AppDisplay(), p,
+ qt_enlightenment_desktop, 0, 1, False, XA_CARDINAL,
+ &type_ret, &i_unused, &l_unused, &l_unused,
+ &data_ret) == Success &&
+ type_ret == XA_CARDINAL)) {
+ if (data_ret)
+ XFree(data_ret);
+
+ break;
+ } else if (qt_net_supports(qt_net_virtual_roots) && qt_net_virtual_root_list) {
+ int i = 0;
+ while (qt_net_virtual_root_list[i] != 0) {
+ if (qt_net_virtual_root_list[i++] == p)
+ break;
+ }
+ }
+
+ l = w;
+ w = p;
+ }
+
+ // we have our window
+ int transx, transy;
+ XWindowAttributes wattr;
+ if (XTranslateCoordinates(QPaintDevice::x11AppDisplay(), l, w,
+ 0, 0, &transx, &transy, &p) &&
+ XGetWindowAttributes(QPaintDevice::x11AppDisplay(), w, &wattr)) {
+ QTLWExtra *top = that->topData();
+ top->fleft = transx;
+ top->ftop = transy;
+ top->fright = wattr.width - crect.width() - top->fleft;
+ top->fbottom = wattr.height - crect.height() - top->ftop;
+
+ // add the border_width for the window managers frame... some window managers
+ // do not use a border_width of zero for their frames, and if we the left and
+ // top strut, we ensure that pos() is absolutely correct. frameGeometry()
+ // will still be incorrect though... perhaps i should have foffset as well, to
+ // indicate the frame offset (equal to the border_width on X).
+ // - Brad
+ top->fleft += wattr.border_width;
+ top->fright += wattr.border_width;
+ top->ftop += wattr.border_width;
+ top->fbottom += wattr.border_width;
+ }
+
+ that->fstrut_dirty = 0;
+}
+
+
+/*!
+ This function returns the widget holding the QInputContext
+ 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 QApplication::locateICHolderWidget().
+
+ This definition enables application developer to change the
+ mapping of widgets to QInputContext instance simply by overriding
+ QApplication::locateICHolderWidget().
+
+ \sa QApplication::locateICHolderWidget()
+*/
+QWidget *QWidget::icHolderWidget()
+{
+ return qApp->locateICHolderWidget(this);
+}
+
+
+/*!
+ This function returns the QInputContext instance for this widget.
+ This instance is used for text input to this widget, etc.
+ It is simply the accessor function.
+*/
+QInputContext *QWidget::getInputContext()
+{
+ QInputContext *qic = 0;
+
+// #if !defined(QT_NO_IM_EXTENSIONS)
+ if ( isInputMethodEnabled() ) {
+#if !defined(QT_NO_IM_EXTENSIONS)
+ qic = icHolderWidget()->ic;
+#else
+// {
+ // icHolderWidget is always topLevelWidget
+ QTLWExtra *topdata = icHolderWidget()->topData();
+ qic = (QInputContext *)topdata->xic;
+#endif
+ }
+
+ return qic;
+}
+
+
+/*!
+ This function replaces the QInputContext instance used for text
+ input to this widget. The \a identifierName is the identifier name
+ of newly choosed input method.
+*/
+void QWidget::changeInputContext( const QString& identifierName )
+{
+ QWidget *icWidget = icHolderWidget();
+#if !defined(QT_NO_IM_EXTENSIONS)
+ QInputContext **qicp = &icWidget->ic;
+#else
+ QInputContext **qicp = (QInputContext **)&icWidget->topData()->xic;
+#endif
+
+ if( *qicp )
+ delete *qicp;
+ // an input context that has the identifierName is generated.
+ QInputContext *qic = QInputContextFactory::create( identifierName, icWidget );
+ *qicp = qic;
+ if ( qic ) {
+ QObject::connect( qic, SIGNAL(imEventGenerated(QObject *,QIMEvent *)),
+ qApp, SLOT(postIMEvent(QObject *,QIMEvent *)) );
+ QObject::connect( qic, SIGNAL(deletionRequested()),
+ icWidget, 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 QT_NO_IM_EXTENSIONS is not set, input context is
+ generated only when isInputMethodEnabled() returns TRUE.
+*/
+void QWidget::createInputContext()
+{
+// #if !defined(QT_NO_IM_EXTENSIONS)
+ if( !isInputMethodEnabled() || QApplication::closingDown() )
+ return;
+// #endif
+
+ QWidget *icWidget = icHolderWidget();
+#ifndef QT_NO_IM
+#if !defined(QT_NO_IM_EXTENSIONS)
+ QInputContext **qicp = &icWidget->ic;
+#else
+ QInputContext **qicp = (QInputContext **)&icWidget->topData()->xic;
+#endif
+
+ if ( ! *qicp ) {
+ // an input context of the default input method is generated.
+ QInputContext *qic = QInputContextFactory::create( QApplication::defaultInputMethod(), icWidget );
+
+ *qicp = qic;
+ if ( qic ) {
+ QObject::connect( qic, SIGNAL(imEventGenerated(QObject *,QIMEvent *)),
+ qApp, SLOT(postIMEvent(QObject *,QIMEvent *)) );
+ QObject::connect( qic, SIGNAL(deletionRequested()),
+ icWidget, SLOT(destroyInputContext()) );
+ }
+ }
+#endif // QT_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 QInputContext::deletionRequested()
+*/
+void QWidget::destroyInputContext()
+{
+#ifndef QT_NO_IM
+#if !defined(QT_NO_IM_EXTENSIONS)
+ QInputContext **qicp = &ic;
+#else
+ if ( ! extra || ! extra->topextra )
+ return;
+
+ QInputContext **qicp = (QInputContext **)&extra->topextra->xic;
+#endif
+
+ if( *qicp )
+ delete *qicp;
+
+ *qicp = 0;
+#endif // QT_NO_IM
+}
+
+
+/*!
+ 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
+ QInputContext for further information.
+
+ \sa QInputContext, unfocusInputContext(), QInputContext::unsetFocus()
+*/
+void QWidget::resetInputContext()
+{
+#ifndef QT_NO_IM
+ // trigger input context creation if it hasn't happened already
+ createInputContext();
+
+ QInputContext *qic = getInputContext();
+ if( qic )
+ qic->reset();
+#endif // QT_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 QInputContext::setFocus()
+ */
+void QWidget::focusInputContext()
+{
+#ifndef QT_NO_IM
+ QWidget* tlw = topLevelWidget();
+
+ if (!tlw->isPopup() || isInputMethodEnabled()) {
+ // trigger input context creation if it hasn't happened already
+ createInputContext();
+
+ QInputContext *qic = getInputContext();
+ if ( qic ) {
+ if( qic->focusWidget() != this ) {
+ qic->setFocusWidget( this );
+ qic->setFocus();
+ }
+ }
+ }
+#endif // QT_NO_IM
+}
+
+
+/*!
+ \internal
+ This is an internal function, you should never call this.
+
+ This function is called to remove focus from associated input
+ context.
+
+ \sa QInputContext::unsetFocus()
+ */
+void QWidget::unfocusInputContext()
+{
+#ifndef QT_NO_IM
+ // trigger input context creation if it hasn't happened already
+ createInputContext();
+
+ QInputContext *qic = getInputContext();
+ if ( qic ) {
+ // may be caused reset() in some input methods
+ qic->unsetFocus();
+ qic->setFocusWidget( 0 );
+ }
+#endif // QT_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 QInputContext::mouseHandler()
+ */
+void QWidget::sendMouseEventToInputContext( int x, QEvent::Type type,
+ Qt::ButtonState button,
+ Qt::ButtonState state )
+{
+#ifndef QT_NO_IM
+ // trigger input context creation if it hasn't happened already
+ createInputContext();
+
+ QInputContext *qic = getInputContext();
+ if ( qic ) {
+ // may be causing reset() in some input methods
+ qic->mouseHandler( x, type, button, state );
+ }
+#endif // QT_NO_IM
+}
+
+
+void QWidget::setWindowOpacity(double)
+{
+}
+
+double QWidget::windowOpacity() const
+{
+ return 1.0;
+}