Some code cleanup, adjustments to match ADS coding style

This commit is contained in:
Uwe Kindler 2020-08-31 08:32:56 +02:00
parent 533d174abc
commit 04aecb3693
7 changed files with 231 additions and 112 deletions

View File

@ -83,7 +83,8 @@ static void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused)
#ifdef Q_OS_LINUX
static void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused)
{
if(FloatingWidget->hasNativeTitleBar()){
if (FloatingWidget->hasNativeTitleBar())
{
return;
}
auto TitleBar = qobject_cast<CFloatingWidgetTitleBar*>(FloatingWidget->titleBarWidget());

View File

@ -493,45 +493,62 @@ CDockManager::~CDockManager()
//============================================================================
#ifdef Q_OS_LINUX
bool CDockManager::eventFilter(QObject *obj, QEvent *e){
bool CDockManager::eventFilter(QObject *obj, QEvent *e)
{
// Emulate Qt:Tool behaviour.
// Required because on some WMs Tool windows can't be maximized.
// Window always on top of the MainWindow.
if(e->type() == QEvent::WindowActivate){
for(auto _window : floatingWidgets()){
if(!_window->isVisible() || window()->isMinimized()){
if (e->type() == QEvent::WindowActivate)
{
for (auto _window : floatingWidgets())
{
if (!_window->isVisible() || window()->isMinimized())
{
continue;
}
// setWindowFlags(Qt::WindowStaysOnTopHint) will hide the window and thus requires a show call.
// This then leads to flickering and a nasty endless loop (also buggy behaviour on Ubuntu).
// So we just do it ourself.
internal::xcb_update_prop(true, _window->window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP");
internal::xcb_update_prop(true, _window->window()->winId(),
"_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP");
}
}
else if(e->type() == QEvent::WindowDeactivate){
for(auto _window : floatingWidgets()){
if(!_window->isVisible() || window()->isMinimized()){
else if (e->type() == QEvent::WindowDeactivate)
{
for (auto _window : floatingWidgets())
{
if (!_window->isVisible() || window()->isMinimized())
{
continue;
}
internal::xcb_update_prop(false, _window->window()->winId(), "_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP");
internal::xcb_update_prop(false, _window->window()->winId(),
"_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP");
_window->raise();
}
}
// Sync minimize with MainWindow
if(e->type() == QEvent::WindowStateChange){
for(auto _window : floatingWidgets()){
if(! _window->isVisible()){
if (e->type() == QEvent::WindowStateChange)
{
for (auto _window : floatingWidgets())
{
if (! _window->isVisible())
{
continue;
}
if(window()->isMinimized()){
if (window()->isMinimized())
{
_window->showMinimized();
} else {
}
else
{
_window->setWindowState(_window->windowState() & (~Qt::WindowMinimized));
}
}
if(!window()->isMinimized()){
if (!window()->isMinimized())
{
QApplication::setActiveWindow(window());
}
}

View File

@ -411,7 +411,8 @@ struct FloatingDockContainerPrivate
void setWindowTitle(const QString &Text)
{
#ifdef Q_OS_LINUX
if(TitleBar){
if (TitleBar)
{
TitleBar->setTitle(Text);
}
#endif
@ -610,24 +611,40 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
QDockWidget::setFloating(true);
QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
bool native_window = true;
// FloatingContainerForce*TitleBar is overwritten by the "ADS_UseNativeTitle" environment variable if set.
auto env = qgetenv("ADS_UseNativeTitle").toUpper();
if (env == "1")
{
native_window = true;
}
else if (env == "0")
{
native_window = false;
}
else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceNativeTitleBar))
{
native_window = true;
}
else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceCustomTitleBar))
{
native_window = false;
}
else
{
// KDE doesn't seem to fire MoveEvents while moving windows, so for now no native titlebar for everything using KWin.
QString window_manager = internal::windowManager().toUpper().split(" ")[0];
bool native_window = window_manager != "KWIN";
// FloatingContainerForce*TitleBar is overwritten by the "ADS_UseNativeTitle" environment variable if set.
auto env = qgetenv("ADS_UseNativeTitle").toUpper();
if (env == "1"){
native_window = true;
} else if (env == "0"){
native_window = false;
} else if ( DockManager->testConfigFlag( CDockManager::FloatingContainerForceNativeTitleBar )){
native_window = true;
} else if ( DockManager->testConfigFlag( CDockManager::FloatingContainerForceCustomTitleBar )){
native_window = false;
}
if(native_window){
if (native_window)
{
setTitleBarWidget(new QWidget());
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
} else {
}
else
{
d->TitleBar = new CFloatingWidgetTitleBar(this);
setTitleBarWidget(d->TitleBar);
setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint);
@ -705,7 +722,8 @@ void CFloatingDockContainer::changeEvent(QEvent *event)
d->zOrderIndex = ++zOrderCounter;
#ifdef Q_OS_LINUX
if(d->DraggingState == DraggingFloatingWidget){
if (d->DraggingState == DraggingFloatingWidget)
{
d->titleMouseReleaseEvent();
d->DraggingState = DraggingInactive;
}
@ -848,20 +866,13 @@ void CFloatingDockContainer::showEvent(QShowEvent *event)
void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
{
#ifndef Q_OS_LINUX
Q_UNUSED(MouseEventHandler)
#endif
#ifdef Q_OS_LINUX
if (!isMaximized()) {
if (!isMaximized())
{
resize(Size);
d->DragStartMousePosition = DragStartMousePos;
}
#else
resize(Size);
d->DragStartMousePosition = DragStartMousePos;
#endif
d->setState(DragState);
#ifdef Q_OS_LINUX
if (DraggingFloatingWidget == DragState)
{
d->MouseEventHandler = MouseEventHandler;
@ -870,15 +881,20 @@ void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
d->MouseEventHandler->grabMouse();
}
}
#endif
#ifdef Q_OS_LINUX
if (!isMaximized()) {
if (!isMaximized())
{
moveFloating();
}
#else
moveFloating();
#endif
show();
#else
Q_UNUSED(MouseEventHandler)
resize(Size);
d->DragStartMousePosition = DragStartMousePos;
d->setState(DragState);
moveFloating();
show();
#endif
}
//============================================================================
@ -988,7 +1004,8 @@ bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream,
}
onDockAreasAddedOrRemoved();
#ifdef Q_OS_LINUX
if(d->TitleBar){
if(d->TitleBar)
{
d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized);
}
#endif
@ -1134,15 +1151,21 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
#ifdef Q_OS_LINUX
//============================================================================
void CFloatingDockContainer::onMaximizeRequest()
{
if(windowState() == Qt::WindowMaximized){
if (windowState() == Qt::WindowMaximized)
{
showNormal();
}else{
}
else
{
showMaximized();
}
}
//============================================================================
void CFloatingDockContainer::showNormal(bool fixGeometry)
{
if (windowState() == Qt::WindowMaximized)
@ -1154,45 +1177,65 @@ void CFloatingDockContainer::showNormal(bool fixGeometry)
setGeometry(oldNormal);
}
}
if(d->TitleBar){
if(d->TitleBar)
{
d->TitleBar->setMaximizedIcon(false);
}
}
//============================================================================
void CFloatingDockContainer::showMaximized()
{
Super::showMaximized();
if(d->TitleBar){
if (d->TitleBar)
{
d->TitleBar->setMaximizedIcon(true);
}
}
//============================================================================
bool CFloatingDockContainer::isMaximized() const
{
return windowState() == Qt::WindowMaximized;
}
void CFloatingDockContainer::show(){
//============================================================================
void CFloatingDockContainer::show()
{
// Prevent this window from showing in the taskbar and pager (alt+tab)
internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_TASKBAR");
internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_PAGER");
Super::show();
}
void CFloatingDockContainer::resizeEvent(QResizeEvent *event){
//============================================================================
void CFloatingDockContainer::resizeEvent(QResizeEvent *event)
{
d->IsResizing = true;
Super::resizeEvent(event);
}
void CFloatingDockContainer::moveEvent(QMoveEvent *event){
//============================================================================
void CFloatingDockContainer::moveEvent(QMoveEvent *event)
{
Super::moveEvent(event);
if(!d->IsResizing && event->spontaneous()){
if (!d->IsResizing && event->spontaneous())
{
d->DraggingState = DraggingFloatingWidget;
d->updateDropOverlays(QCursor::pos());
}
d->IsResizing = false;
}
bool CFloatingDockContainer::hasNativeTitleBar(){
//============================================================================
bool CFloatingDockContainer::hasNativeTitleBar()
{
return d->TitleBar == nullptr;
}
#endif

View File

@ -284,6 +284,10 @@ public:
*/
void show();
/**
* Returns true if the floating widget has a native titlebar or false if
* the floating widget has a QWidget based title bar
*/
bool hasNativeTitleBar();
#endif

View File

@ -53,33 +53,44 @@ namespace ads
namespace internal
{
#ifdef Q_OS_LINUX
static QString _window_manager;
static QHash<QString, xcb_atom_t> _xcb_atom_cache;
static QString _window_manager;
static QHash<QString, xcb_atom_t> _xcb_atom_cache;
xcb_atom_t xcb_get_atom(const char *name){
if (!QX11Info::isPlatformX11()){
//============================================================================
xcb_atom_t xcb_get_atom(const char *name)
{
if (!QX11Info::isPlatformX11())
{
return XCB_ATOM_NONE;
}
auto key = QString(name);
if(_xcb_atom_cache.contains(key)){
if(_xcb_atom_cache.contains(key))
{
return _xcb_atom_cache[key];
}
xcb_connection_t *connection = QX11Info::connection();
xcb_intern_atom_cookie_t request = xcb_intern_atom(connection, 1, strlen(name), name);
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, request, NULL);
if(!reply){
if (!reply)
{
return XCB_ATOM_NONE;
}
xcb_atom_t atom = reply->atom;
if(atom == XCB_ATOM_NONE){
if(atom == XCB_ATOM_NONE)
{
ADS_PRINT("Unknown Atom response from XServer: " << name);
} else {
}
else
{
_xcb_atom_cache.insert(key, atom);
}
free(reply);
return atom;
}
//============================================================================
void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2)
{
auto connection = QX11Info::connection();
@ -103,18 +114,24 @@ void xcb_update_prop(bool set, WId window, const char *type, const char *prop, c
xcb_flush(connection);
}
xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type){
if (!QX11Info::isPlatformX11()){
//============================================================================
xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type)
{
if (!QX11Info::isPlatformX11())
{
return nullptr;
}
xcb_connection_t *connection = QX11Info::connection();
xcb_atom_t type_atom = xcb_get_atom(type);
if (type_atom == XCB_ATOM_NONE){
if (type_atom == XCB_ATOM_NONE)
{
return nullptr;
}
xcb_get_property_cookie_t request = xcb_get_property_unchecked(connection, 0, window, type_atom, atom_type, 0, 1024);
xcb_get_property_reply_t *reply = xcb_get_property_reply(connection, request, nullptr);
if(reply && reply->type != atom_type){
if(reply && reply->type != atom_type)
{
ADS_PRINT("ATOM TYPE MISMATCH (" << type <<"). Expected: " << atom_type << " but got " << reply->type);
free(reply);
return nullptr;
@ -122,10 +139,14 @@ xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned
return reply;
}
//============================================================================
template <typename T>
void xcb_get_prop_list(WId window, const char *type, QVector<T> &ret, unsigned int atom_type){
void xcb_get_prop_list(WId window, const char *type, QVector<T> &ret, unsigned int atom_type)
{
xcb_get_property_reply_t *reply = _xcb_get_props(window, type, atom_type);
if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0) {
if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0)
{
const xcb_atom_t *data = static_cast<const T *>(xcb_get_property_value(reply));
ret.resize(reply->value_len);
memcpy((void *)&ret.first(), (void *)data, reply->value_len * sizeof(T));
@ -133,13 +154,18 @@ void xcb_get_prop_list(WId window, const char *type, QVector<T> &ret, unsigned i
free(reply);
}
QString xcb_get_prop_string(WId window, const char *type){
//============================================================================
QString xcb_get_prop_string(WId window, const char *type)
{
QString ret;
// try utf8 first
xcb_atom_t utf_atom = xcb_get_atom("UTF8_STRING");
if(utf_atom != XCB_ATOM_NONE){
if(utf_atom != XCB_ATOM_NONE)
{
xcb_get_property_reply_t *reply = _xcb_get_props(window, type, utf_atom);
if (reply && reply->format == 8 && reply->type == utf_atom) {
if (reply && reply->format == 8 && reply->type == utf_atom)
{
const char *value = reinterpret_cast<const char *>(xcb_get_property_value(reply));
ret = QString::fromUtf8(value, xcb_get_property_value_length(reply));
free(reply);
@ -149,7 +175,8 @@ QString xcb_get_prop_string(WId window, const char *type){
}
// Fall back to XCB_ATOM_STRING
xcb_get_property_reply_t *reply = _xcb_get_props(window, type, XCB_ATOM_STRING);
if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) {
if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING)
{
const char *value = reinterpret_cast<const char *>(xcb_get_property_value(reply));
ret = QString::fromLatin1(value, xcb_get_property_value_length(reply));
}
@ -157,12 +184,16 @@ QString xcb_get_prop_string(WId window, const char *type){
return ret;
}
bool xcb_dump_props(WId window, const char *type){
//============================================================================
bool xcb_dump_props(WId window, const char *type)
{
QVector<xcb_atom_t> atoms;
xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM);
qDebug() << "\n\n!!!" << type << " - " << atoms.length();
xcb_connection_t *connection = QX11Info::connection();
for(auto atom : atoms){
for (auto atom : atoms)
{
auto foo = xcb_get_atom_name(connection, atom);
auto bar = xcb_get_atom_name_reply(connection, foo, nullptr);
qDebug() << "\t" << xcb_get_atom_name_name(bar);
@ -171,21 +202,29 @@ bool xcb_dump_props(WId window, const char *type){
return true;
}
void xcb_add_prop(bool state, WId window, const char *type, const char *prop){
if (!QX11Info::isPlatformX11()){
//============================================================================
void xcb_add_prop(bool state, WId window, const char *type, const char *prop)
{
if (!QX11Info::isPlatformX11())
{
return;
}
xcb_atom_t prop_atom = xcb_get_atom(prop);
xcb_atom_t type_atom = xcb_get_atom(type);
if(prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE){
if (prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE)
{
return;
}
QVector<xcb_atom_t> atoms;
xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM);
int index = atoms.indexOf(prop_atom);
if(state && index == -1){
if (state && index == -1)
{
atoms.push_back(prop_atom);
} else if(!state && index >= 0){
}
else if (!state && index >= 0)
{
atoms.remove(index);
}
xcb_connection_t *connection = QX11Info::connection();
@ -193,15 +232,20 @@ void xcb_add_prop(bool state, WId window, const char *type, const char *prop){
xcb_flush(connection);
}
QString detectWindowManagerX11(){
//============================================================================
QString detectWindowManagerX11()
{
// Tries to detect the windowmanager via X11.
// See: https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html#idm46018259946000
if (!QX11Info::isPlatformX11()){
if (!QX11Info::isPlatformX11())
{
return "UNKNOWN";
}
xcb_connection_t *connection = QX11Info::connection();
xcb_screen_t *first_screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;
if(!first_screen){
if(!first_screen)
{
ADS_PRINT("No screen found via XCB.");
return "UNKNOWN";
}
@ -210,26 +254,32 @@ QString detectWindowManagerX11(){
xcb_window_t support_win = 0;
QVector<xcb_window_t> sup_windows;
xcb_get_prop_list(root, "_NET_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_WINDOW);
if(sup_windows.length() == 0){
if(sup_windows.length() == 0)
{
// This doesn't seem to be in use anymore, but wmctrl does the same so lets play safe.
// Both XCB_ATOM_CARDINAL and XCB_ATOM_WINDOW break down to a uint32_t, so reusing sup_windows should be fine.
xcb_get_prop_list(root, "_WIN_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_CARDINAL);
}
if(sup_windows.length() == 0){
if(sup_windows.length() == 0)
{
ADS_PRINT("Failed to get the supporting window on non EWMH comform WM.");
return "UNKNOWN";
}
support_win = sup_windows[0];
QString ret = xcb_get_prop_string(support_win, "_NET_WM_NAME");
if(ret.length() == 0){
if(ret.length() == 0)
{
ADS_PRINT("Empty WM name occured.");
return "UNKNOWN";
}
return ret;
}
QString windowManager(){
if(_window_manager.length() == 0){
//============================================================================
QString windowManager()
{
if(_window_manager.length() == 0)
{
_window_manager = detectWindowManagerX11();
}
return _window_manager;

View File

@ -135,30 +135,30 @@ static const char* const ClosedProperty = "close";
static const char* const DirtyProperty = "dirty";
#ifdef Q_OS_LINUX
// Utils to directly communicate with the X server
/**
// Utils to directly communicate with the X server
/**
* Get atom from cache or request it from the XServer.
*/
xcb_atom_t xcb_get_atom(const char *name);
xcb_atom_t xcb_get_atom(const char *name);
/**
/**
* Add a property to a window. Only works on "hidden" windows.
*/
void xcb_add_prop(bool state, WId window, const char *type, const char *prop);
/**
void xcb_add_prop(bool state, WId window, const char *type, const char *prop);
/**
* Updates up to two window properties. Can be set on a visible window.
*/
void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2 = nullptr);
/**
void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2 = nullptr);
/**
* Only for debugging purposes.
*/
bool xcb_dump_props(WId window, const char *type);
/**
bool xcb_dump_props(WId window, const char *type);
/**
* Gets the active window manager from the X11 Server.
* Requires a EWMH conform window manager (Allmost all common used ones are).
* Returns "UNKNOWN" otherwise.
*/
QString windowManager();
QString windowManager();
#endif
/**

View File

@ -154,6 +154,7 @@ void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent *ev)
Super::mousePressEvent(ev);
}
//============================================================================
void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev)
{
@ -165,6 +166,7 @@ void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev)
Super::mouseReleaseEvent(ev);
}
//============================================================================
void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev)
{
@ -178,12 +180,10 @@ void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev)
// move floating window
if (DraggingFloatingWidget == d->DragState)
{
#ifdef Q_OS_LINUX
if(d->FloatingWidget->isMaximized())
{
d->FloatingWidget->showNormal(true);
}
#endif
d->FloatingWidget->moveFloating();
Super::mouseMoveEvent(ev);
return;
@ -211,6 +211,8 @@ void CFloatingWidgetTitleBar::updateStyle()
internal::repolishStyle(this, internal::RepolishDirectChildren);
}
//============================================================================
void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
@ -224,6 +226,8 @@ void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
}
}
//============================================================================
void CFloatingWidgetTitleBar::setMaximizedIcon(bool maximized)
{
if (maximized)