From 0eb9f5e217225129b22de1a48fe7300723456da3 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Thu, 26 Jan 2012 16:34:00 -0600 Subject: [PATCH] Add NetWM/Motif controls to QWidget This must break binary compatibility, so version was also bumped to 3.4.0 --- changes-3.4 | 13 ++++++ src/kernel/qapplication_x11.cpp | 34 ++++++++++++-- src/kernel/qnamespace.h | 22 +++++++++ src/kernel/qwidget.cpp | 20 +++++++++ src/kernel/qwidget.h | 48 ++++++++++++++------ src/kernel/qwidget_x11.cpp | 79 +++++++++++++++++++++++++++++++++ src/tools/qglobal.h | 4 +- 7 files changed, 200 insertions(+), 20 deletions(-) create mode 100644 changes-3.4 diff --git a/changes-3.4 b/changes-3.4 new file mode 100644 index 0000000..09cc65d --- /dev/null +++ b/changes-3.4 @@ -0,0 +1,13 @@ +Qt 3.4 is a new feature release. It is not backwards compatible with any +prior Qt3 version due to changes in the QWidget definition. + +**************************************************************************** +* General * +**************************************************************************** + +General Improvements +-------------------- + +- Technical + + * Add QWidget NetWM control flags diff --git a/src/kernel/qapplication_x11.cpp b/src/kernel/qapplication_x11.cpp index 7bc9f48..45d83df 100644 --- a/src/kernel/qapplication_x11.cpp +++ b/src/kernel/qapplication_x11.cpp @@ -262,9 +262,22 @@ Atom qt_net_wm_state = 0; Atom qt_net_wm_state_modal = 0; Atom qt_net_wm_state_max_v = 0; Atom qt_net_wm_state_max_h = 0; -Atom qt_net_wm_state_fullscreen = 0; -Atom qt_net_wm_state_above = 0; -Atom qt_net_wm_window_type = 0; +Atom qt_net_wm_state_fullscreen = 0; +Atom qt_net_wm_state_above = 0; +Atom qt_net_wm_action = 0; +Atom qt_net_wm_action_move = 0; +Atom qt_net_wm_action_resize = 0; +Atom qt_net_wm_action_minimize = 0; +Atom qt_net_wm_action_shade = 0; +Atom qt_net_wm_action_stick = 0; +Atom qt_net_wm_action_max_h = 0; +Atom qt_net_wm_action_max_v = 0; +Atom qt_net_wm_action_fullscreen = 0; +Atom qt_net_wm_action_change_desktop = 0; +Atom qt_net_wm_action_close = 0; +Atom qt_net_wm_action_above = 0; +Atom qt_net_wm_action_below = 0; +Atom qt_net_wm_window_type = 0; Atom qt_net_wm_window_type_normal = 0; Atom qt_net_wm_window_type_dialog = 0; Atom qt_net_wm_window_type_toolbar = 0; @@ -2003,6 +2016,19 @@ void qt_init_internal( int *argcptr, char **argv, qt_x11_intern_atom( "_NET_WM_STATE_MAXIMIZED_HORZ", &qt_net_wm_state_max_h ); qt_x11_intern_atom( "_NET_WM_STATE_FULLSCREEN", &qt_net_wm_state_fullscreen ); qt_x11_intern_atom( "_NET_WM_STATE_ABOVE", &qt_net_wm_state_above ); + qt_x11_intern_atom( "_NET_WM_ALLOWED_ACTIONS", &qt_net_wm_action ); + qt_x11_intern_atom( "_NET_WM_ACTION_MOVE", &qt_net_wm_action_move ); + qt_x11_intern_atom( "_NET_WM_ACTION_RESIZE", &qt_net_wm_action_resize ); + qt_x11_intern_atom( "_NET_WM_ACTION_MINIMIZE", &qt_net_wm_action_minimize ); + qt_x11_intern_atom( "_NET_WM_ACTION_SHADE", &qt_net_wm_action_shade ); + qt_x11_intern_atom( "_NET_WM_ACTION_STICK", &qt_net_wm_action_stick ); + qt_x11_intern_atom( "_NET_WM_ACTION_MAXIMIZE_HORZ", &qt_net_wm_action_max_h ); + qt_x11_intern_atom( "_NET_WM_ACTION_MAXIMIZE_VERT", &qt_net_wm_action_max_v ); + qt_x11_intern_atom( "_NET_WM_ACTION_FULLSCREEN", &qt_net_wm_action_fullscreen ); + qt_x11_intern_atom( "_NET_WM_ACTION_CHANGE_DESKTOP", &qt_net_wm_action_change_desktop ); + qt_x11_intern_atom( "_NET_WM_ACTION_CLOSE", &qt_net_wm_action_close ); + qt_x11_intern_atom( "_NET_WM_ACTION_ABOVE", &qt_net_wm_action_above ); + qt_x11_intern_atom( "_NET_WM_ACTION_BELOW", &qt_net_wm_action_below ); qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE", &qt_net_wm_window_type ); qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_NORMAL", &qt_net_wm_window_type_normal ); qt_x11_intern_atom( "_NET_WM_WINDOW_TYPE_DIALOG", &qt_net_wm_window_type_dialog ); @@ -5167,7 +5193,7 @@ bool QETWidget::translateKeyEventInternal( const XEvent *event, int& count, 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 - // XLookupString to return things like 'å' (aring) for ALT-A. This + // XLookupString to return things like '�' (aring) for ALT-A. This // completely breaks modifiers. If we remove the modifier for Mode_switch, // then things work correctly... xkeyevent.state &= ~qt_mode_switch_remove_mask; diff --git a/src/kernel/qnamespace.h b/src/kernel/qnamespace.h index 1598785..2201a3d 100644 --- a/src/kernel/qnamespace.h +++ b/src/kernel/qnamespace.h @@ -168,6 +168,28 @@ public: WState_HasMouse = 0x00800000 }; + // NetWM flags; documented in qwidget.cpp + typedef uint NFlags; + + // documented in qwidget.cpp + enum NETWMFlags { +#if defined(Q_WS_X11) + WX11DisableMove = 0x00000001, + WX11DisableClose = 0x00000002, + WX11DisableResize = 0x00000004, + WX11DisableMinimize = 0x00000008, + WX11DisableMaximize = 0x00000010, + WX11DisableShade = 0x00000020 +#else + WX11DisableMove = 0x00000000, + WX11DisableClose = 0x00000000, + WX11DisableResize = 0x00000000, + WX11DisableMinimize = 0x00000000, + WX11DisableMaximize = 0x00000000, + WX11DisableShade = 0x00000000 +#endif + }; + // Widget flags2; documented in qwidget.cpp typedef uint WFlags; diff --git a/src/kernel/qwidget.cpp b/src/kernel/qwidget.cpp index 856907c..65aabb4 100644 --- a/src/kernel/qwidget.cpp +++ b/src/kernel/qwidget.cpp @@ -775,6 +775,25 @@ QSize qt_naturalWidgetSize( QWidget *w ) { */ +/*! + \enum Qt::NETWMFlags + + \keyword NETWM flag + + This enum type is used to specify various NETWM properties + under X11 and similar systems. + + The main types are + + \value WX11DisableMove + \value WX11DisableClose + \value WX11DisableResize + \value WX11DisableMinimize + \value WX11DisableMaximize + \value WX11DisableShade + +*/ + /*! \enum Qt::WidgetState @@ -874,6 +893,7 @@ QWidget::QWidget( QWidget *parent, const char *name, WFlags f ) winid = 0; // default attributes widget_state = 0; widget_flags = f; + netwm_flags = 0; focus_policy = 0; own_font = 0; own_palette = 0; diff --git a/src/kernel/qwidget.h b/src/kernel/qwidget.h index c83acb5..f77ca3a 100644 --- a/src/kernel/qwidget.h +++ b/src/kernel/qwidget.h @@ -455,6 +455,7 @@ public: QWidget * parentWidget( bool sameWindow = FALSE ) const; WState testWState( WState s ) const; WFlags testWFlags( WFlags f ) const; + NFlags testNFlags( NFlags f ) const; static QWidget * find( WId ); static QWidgetMapper *wmapper(); @@ -578,6 +579,9 @@ protected: WFlags getWFlags() const; virtual void setWFlags( WFlags ); void clearWFlags( WFlags n ); + NFlags getNFlags() const; + virtual void setNFlags( NFlags ); + void clearNFlags( NFlags n ); virtual bool focusNextPrevChild( bool next ); @@ -665,20 +669,25 @@ private: void setBackgroundX11Relative(); #endif - WId winid; - uint widget_state; - uint widget_flags; - uint focus_policy : 4; - uint own_font :1; - uint own_palette :1; - uint sizehint_forced :1; - uint is_closing :1; - uint in_show : 1; - uint in_show_maximized : 1; - uint fstrut_dirty : 1; - uint im_enabled : 1; - QRect crect; - QColor bg_col; + WId winid; + uint widget_state; + uint widget_flags; + uint netwm_flags; + uint reserved_1; + uint reserved_2; + uint reserved_3; + uint reserved_4; + uint focus_policy : 4; + uint own_font :1; + uint own_palette :1; + uint sizehint_forced :1; + uint is_closing :1; + uint in_show : 1; + uint in_show_maximized : 1; + uint fstrut_dirty : 1; + uint im_enabled : 1; + QRect crect; + QColor bg_col; #ifndef QT_NO_PALETTE QPalette pal; #endif @@ -756,6 +765,8 @@ inline Qt::WState QWidget::testWState( WState s ) const inline Qt::WFlags QWidget::testWFlags( WFlags f ) const { return (widget_flags & f); } +inline Qt::NFlags QWidget::testNFlags( NFlags f ) const +{ return (netwm_flags & f); } inline WId QWidget::winId() const { return winid; } @@ -916,12 +927,21 @@ inline void QWidget::clearWState( uint f ) inline Qt::WFlags QWidget::getWFlags() const { return widget_flags; } +inline Qt::NFlags QWidget::getNFlags() const +{ return netwm_flags; } + inline void QWidget::setWFlags( WFlags f ) { widget_flags |= f; } +inline void QWidget::setNFlags( NFlags f ) +{ netwm_flags |= f; } + inline void QWidget::clearWFlags( WFlags f ) { widget_flags &= ~f; } +inline void QWidget::clearNFlags( NFlags f ) +{ netwm_flags &= ~f; } + inline void QWidget::constPolish() const { if ( !testWState(WState_Polished) ) { diff --git a/src/kernel/qwidget_x11.cpp b/src/kernel/qwidget_x11.cpp index 02fdebf..775829c 100644 --- a/src/kernel/qwidget_x11.cpp +++ b/src/kernel/qwidget_x11.cpp @@ -124,6 +124,19 @@ 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_action; +extern Atom qt_net_wm_action_move; +extern Atom qt_net_wm_action_resize; +extern Atom qt_net_wm_action_minimize; +extern Atom qt_net_wm_action_shade; +extern Atom qt_net_wm_action_stick; +extern Atom qt_net_wm_action_max_h; +extern Atom qt_net_wm_action_max_v; +extern Atom qt_net_wm_action_fullscreen; +extern Atom qt_net_wm_action_change_desktop; +extern Atom qt_net_wm_action_close; +extern Atom qt_net_wm_action_above; +extern Atom qt_net_wm_action_below; extern Atom qt_net_wm_window_type; extern Atom qt_net_wm_window_type_normal; extern Atom qt_net_wm_window_type_dialog; @@ -462,7 +475,16 @@ void QWidget::create( WId window, bool initializeWindow, bool destroyOldWindow) // NET window states long net_winstates[6] = { 0, 0, 0, 0, 0, 0 }; + long net_winactions[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int curr_winstate = 0; + int curr_winaction = 0; + + // Add all default actions that cannot be turned off + net_winactions[curr_winaction++] = qt_net_wm_action_stick; + net_winactions[curr_winaction++] = qt_net_wm_action_fullscreen; + net_winactions[curr_winaction++] = qt_net_wm_action_change_desktop; + net_winactions[curr_winaction++] = qt_net_wm_action_above; + net_winactions[curr_winaction++] = qt_net_wm_action_below; struct { ulong flags, functions, decorations; @@ -475,6 +497,56 @@ void QWidget::create( WId window, bool initializeWindow, bool destroyOldWindow) mwmhints.input_mode = 0L; mwmhints.status = 0L; + if ( testNFlags(WX11DisableResize) ) { + mwmhints.functions |= (1L << 1); // MWM_FUNC_RESIZE + mwmhints.functions |= (1L << 0); // MWM_FUNC_ALL + mwmhints.flags |= (1L << 0); // MWM_HINTS_FUNCTIONS + } + else { + net_winactions[curr_winaction++] = qt_net_wm_action_resize; + } + + if ( testNFlags(WX11DisableMove) ) { + mwmhints.functions |= (1L << 2); // MWM_FUNC_MOVE + mwmhints.functions |= (1L << 0); // MWM_FUNC_ALL + mwmhints.flags |= (1L << 0); // MWM_HINTS_FUNCTIONS + } + else { + net_winactions[curr_winaction++] = qt_net_wm_action_move; + } + + if ( testNFlags(WX11DisableMinimize) ) { + mwmhints.functions |= (1L << 3); // MWM_FUNC_MINIMIZE + mwmhints.functions |= (1L << 0); // MWM_FUNC_ALL + mwmhints.flags |= (1L << 0); // MWM_HINTS_FUNCTIONS + } + else { + net_winactions[curr_winaction++] = qt_net_wm_action_minimize; + } + + if ( testNFlags(WX11DisableMaximize) ) { + mwmhints.functions |= (1L << 4); // MWM_FUNC_MAXIMIZE + mwmhints.functions |= (1L << 0); // MWM_FUNC_ALL + mwmhints.flags |= (1L << 0); // MWM_HINTS_FUNCTIONS + } + else { + net_winactions[curr_winaction++] = qt_net_wm_action_max_h; + net_winactions[curr_winaction++] = qt_net_wm_action_max_v; + } + + if ( testNFlags(WX11DisableClose) ) { + mwmhints.functions |= (1L << 5); // MWM_FUNC_CLOSE + mwmhints.functions |= (1L << 0); // MWM_FUNC_ALL + mwmhints.flags |= (1L << 0); // MWM_HINTS_FUNCTIONS + } + else { + net_winactions[curr_winaction++] = qt_net_wm_action_close; + } + + if ( ! testNFlags(WX11DisableShade) ) { + net_winactions[curr_winaction++] = qt_net_wm_action_shade; + } + if (topLevel && ! (desktop || popup)) { ulong wsa_mask = 0; @@ -630,6 +702,13 @@ void QWidget::create( WId window, bool initializeWindow, bool destroyOldWindow) else XDeleteProperty(dpy, id, qt_net_wm_state); + // set _NET_WM_ALLOWED_ACTIONS + if (curr_winaction > 0) + XChangeProperty(dpy, id, qt_net_wm_action, XA_ATOM, 32, PropModeReplace, + (unsigned char *) net_winactions, curr_winaction); + else + XDeleteProperty(dpy, id, qt_net_wm_action); + // set _NET_WM_PID long curr_pid = getpid(); XChangeProperty(dpy, id, qt_net_wm_pid, XA_CARDINAL, 32, PropModeReplace, diff --git a/src/tools/qglobal.h b/src/tools/qglobal.h index 0fbd4aa..44e6bbf 100644 --- a/src/tools/qglobal.h +++ b/src/tools/qglobal.h @@ -41,11 +41,11 @@ #ifndef QGLOBAL_H #define QGLOBAL_H -#define QT_VERSION_STR "3.3.8d" +#define QT_VERSION_STR "3.4.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x030308 +#define QT_VERSION 0x030400 /* The operating system, must be one of: (Q_OS_x)