diff options
17 files changed, 499 insertions, 53 deletions
diff --git a/src-qt5/core-utils/lumina-config/pages/page_interface_panels.cpp b/src-qt5/core-utils/lumina-config/pages/page_interface_panels.cpp index 827061af..3c355aa7 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_interface_panels.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_interface_panels.cpp @@ -21,6 +21,13 @@ page_interface_panels::page_interface_panels(QWidget *parent) : PageWidget(paren connect(ui->tool_panels_add, SIGNAL(clicked()), this, SLOT(newPanel()) ); updateIcons(); setupProfiles(); + + //Create panels container + QHBoxLayout *panels_layout = new QHBoxLayout(); + panels_layout->setContentsMargins(0,0,0,0); + panels_layout->setAlignment(Qt::AlignLeft); + panels_layout->addStretch(); + ui->scroll_panels->widget()->setLayout(panels_layout); } page_interface_panels::~page_interface_panels(){ @@ -53,28 +60,30 @@ void page_interface_panels::LoadSettings(int screennum){ QString screenID = QApplication::screens().at(cscreen)->name(); QString DPrefix = "desktop-"+screenID+"/"; int panelnumber = settings->value(DPrefix+"panels",-1).toInt(); + QBoxLayout *panels_layout = static_cast<QHBoxLayout*>(ui->scroll_panels->widget()->layout()); -//First clean any current panels - for(int i=0; i<PANELS.length(); i++){ delete PANELS.takeAt(i); i--; } - //Now create new panels - if(ui->scroll_panels->widget()->layout()==0){ - ui->scroll_panels->widget()->setLayout( new QHBoxLayout() ); - ui->scroll_panels->widget()->layout()->setContentsMargins(0,0,0,0); + //Remove extra panels (if any) + for(int i=panelnumber; i<PANELS.length(); i++){ + PanelWidget *tmp = PANELS.takeAt(i); + delete tmp; + i--; } - ui->scroll_panels->widget()->layout()->setAlignment(Qt::AlignLeft); - //Clear anything left over in the layout - for(int i=0; i<ui->scroll_panels->widget()->layout()->count(); i++){ - delete ui->scroll_panels->widget()->layout()->takeAt(i); + + int current_count = panels_layout->count()-1; + + //Update current panels + for(int i=0; i<current_count; i++) { + PANELS[i]->LoadSettings(settings, cscreen, i); } - for(int i=0; i<panelnumber; i++){ + //Create new panels + for(int i=current_count; i<panelnumber; i++){ PanelWidget *tmp = new PanelWidget(ui->scroll_panels->widget(), this, PINFO); tmp->LoadSettings(settings, cscreen, i); PANELS << tmp; connect(tmp, SIGNAL(PanelChanged()), this, SLOT(panelValChanged()) ); connect(tmp, SIGNAL(PanelRemoved(int)), this, SLOT(removePanel(int)) ); - ui->scroll_panels->widget()->layout()->addWidget(tmp); + panels_layout->insertWidget(panels_layout->count()-1, tmp); } - static_cast<QHBoxLayout*>(ui->scroll_panels->widget()->layout())->addStretch(); QApplication::processEvents(); loading = false; diff --git a/src-qt5/core/libLumina/LuminaX11.cpp b/src-qt5/core/libLumina/LuminaX11.cpp index c586790b..e9eb4b7c 100644 --- a/src-qt5/core/libLumina/LuminaX11.cpp +++ b/src-qt5/core/libLumina/LuminaX11.cpp @@ -1470,7 +1470,17 @@ void LXCB::WM_ICCCM_SetProtocols(WId win, LXCB::ICCCM_PROTOCOLS flags){ // _NET_SUPPORTED (Root) void LXCB::WM_Set_Root_Supported(){ //NET_WM standards (ICCCM implied - no standard way to list those) - xcb_atom_t list[] = {}; + xcb_atom_t list[] = {EWMH._NET_WM_NAME, + EWMH._NET_WM_ICON, + EWMH._NET_WM_ICON_NAME, + EWMH._NET_WM_DESKTOP, + /*_NET_WINDOW_TYPE (and all the various types)*/ + EWMH._NET_WM_WINDOW_TYPE, EWMH._NET_WM_WINDOW_TYPE_DESKTOP, EWMH._NET_WM_WINDOW_TYPE_DOCK, + EWMH._NET_WM_WINDOW_TYPE_TOOLBAR, EWMH._NET_WM_WINDOW_TYPE_MENU, EWMH._NET_WM_WINDOW_TYPE_UTILITY, + EWMH._NET_WM_WINDOW_TYPE_SPLASH, EWMH._NET_WM_WINDOW_TYPE_DIALOG, EWMH._NET_WM_WINDOW_TYPE_NORMAL, + EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU, EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU, EWMH._NET_WM_WINDOW_TYPE_TOOLTIP, + EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION, EWMH._NET_WM_WINDOW_TYPE_COMBO, EWMH._NET_WM_WINDOW_TYPE_DND, + }; xcb_ewmh_set_supported(&EWMH, QX11Info::appScreen(), 0,list); } @@ -1611,18 +1621,21 @@ WId LXCB::WM_Get_Active_Window(){ void LXCB::WM_Set_Active_Window(WId win){ xcb_ewmh_set_active_window(&EWMH, QX11Info::appScreen(), win); //Also send the active window a message to take input focus - xcb_client_message_event_t event; + //Send the window a WM_TAKE_FOCUS message + if(atoms.isEmpty()){ createWMAtoms(); } //need these atoms + xcb_client_message_event_t event; event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; - event.window = win; //window to activate + event.window = win; event.type = ATOMS[atoms.indexOf("WM_PROTOCOLS")]; - event.data.data32[0] = ATOMS[atoms.indexOf("WM_TAKE_FOCUS")]; - event.data.data32[1] = QX11Info::getTimestamp(); //current timestamp + event.data.data32[0] = ATOMS[atoms.indexOf("WM_TAKE_FOCUS")]; + event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime; event.data.data32[2] = 0; event.data.data32[3] = 0; event.data.data32[4] = 0; - xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + xcb_flush(QX11Info::connection()); } // _NET_WORKAREA diff --git a/src-qt5/core/libLumina/LuminaX11.h b/src-qt5/core/libLumina/LuminaX11.h index dd9f8213..2f66ce06 100644 --- a/src-qt5/core/libLumina/LuminaX11.h +++ b/src-qt5/core/libLumina/LuminaX11.h @@ -23,7 +23,6 @@ #include <QObject> #include <QFlags> - #include <xcb/xcb_ewmh.h> //SYSTEM TRAY STANDARD DEFINITIONS diff --git a/src-qt5/core/libLumina/NativeWindow.h b/src-qt5/core/libLumina/NativeWindow.h index c4fdbb47..59b955c3 100644 --- a/src-qt5/core/libLumina/NativeWindow.h +++ b/src-qt5/core/libLumina/NativeWindow.h @@ -24,21 +24,29 @@ class NativeWindow : public QObject{ Q_OBJECT public: + enum State{ S_MODAL, S_STICKY, S_MAX_VERT, S_MAX_HORZ, S_SHADED, S_SKIP_TASKBAR, S_SKIP_PAGER, S_HIDDEN, S_FULLSCREEN, S_ABOVE, S_BELOW, S_ATTENTION }; + enum Type{T_DESKTOP, T_DOCK, T_TOOLBAR, T_MENU, T_UTILITY, T_SPLASH, T_DIALOG, T_DROPDOWN_MENU, T_POPUP_MENU, T_TOOLTIP, T_NOTIFICATION, T_COMBO, T_DND, T_NORMAL }; + enum Action {A_MOVE, A_RESIZE, A_MINIMIZE, A_SHADE, A_STICK, A_MAX_VERT, A_MAX_HORZ, A_FULLSCREEN, A_CHANGE_DESKTOP, A_CLOSE, A_ABOVE, A_BELOW}; + enum Property{ /*QVariant Type*/ None, /*null*/ MinSize, /*QSize*/ MaxSize, /*QSize*/ - Size, /*int*/ + Size, /*QSize*/ + GlobalPos, /*QPoint*/ Title, /*QString*/ ShortTitle, /*QString*/ Icon, /*QIcon*/ Name, /*QString*/ Workspace, /*int*/ - WindowFlags, /*Qt::WindowFlags*/ + States, /*QList<NativeWindow::State> : Current state of the window */ + WinTypes, /*QList<NativeWindow::Type> : Current type of window (typically does not change)*/ + WinActions, /*QList<NativeWindow::Action> : Current actions that the window allows (Managed/set by the WM)*/ Active, /*bool*/ Visible /*bool*/ }; + NativeWindow(WId id); ~NativeWindow(); @@ -58,11 +66,14 @@ signals: void PropertyChanged(NativeWindow::Property, QVariant); void WindowClosed(WId); - //Action Requests (not automatically emitted) + //Action Requests (not automatically emitted - typically used to ask the WM to do something) //Note: "WId" should be the NativeWindow id() - void RequestActivate(WId); - void RequestClose(WId); - + void RequestActivate(WId); //Activate the window + void RequestClose(WId); //Close the window + void RequestSetVisible(WId, bool); //Minimize/restore visiblility + void RequestSetGeometry(WId, QRect); //Register the location/size of the window + void RequestSetFrameExtents(WId, QList<int>); //Register the size of the frame around the window [Left,Right, Top,Bottom] in pixels + // System Tray Icon Embed/Unembed Requests //void RequestEmbed(WId, QWidget*); //void RequestUnEmbed(WId, QWidget*); diff --git a/src-qt5/core/libLumina/NativeWindowSystem.cpp b/src-qt5/core/libLumina/NativeWindowSystem.cpp new file mode 100644 index 00000000..c8e6d483 --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindowSystem.cpp @@ -0,0 +1,221 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the XCB version of the NativeWindowSystem class, +// used for interacting with the X11 display system on BSD/Linux/Unix systems +//=========================================== +#include "NativeWindowSystem.h" + +//Additional Qt includes +#include <QX11Info> +#include <QDebug> + +//XCB Library functions +#include <xcb/xcb_ewmh.h> + +//XCB Library includes +#include <xcb/xcb.h> +#include <xcb/xcb_atom.h> +#include <xcb/xproto.h> +#include <xcb/xcb_ewmh.h> +#include <xcb/xcb_icccm.h> +#include <xcb/xcb_image.h> +#include <xcb/xcb_aux.h> +#include <xcb/composite.h> +#include <xcb/damage.h> + +//XLib includes (XCB Damage lib does not appear to register for damage events properly) +#include <X11/extensions/Xdamage.h> + +//SYSTEM TRAY STANDARD DEFINITIONS +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 +#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1 +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 + +#define URGENCYHINT (1L << 8) //For window urgency detection + +#define ROOT_WIN_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ + XCB_EVENT_MASK_BUTTON_PRESS | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_POINTER_MOTION | \ + XCB_EVENT_MASK_PROPERTY_CHANGE | \ + XCB_EVENT_MASK_FOCUS_CHANGE | \ + XCB_EVENT_MASK_ENTER_WINDOW) + +//Internal XCB private objects class +class NativeWindowSystem::p_objects{ +public: + xcb_ewmh_connection_t EWMH; //This is where all the screen info and atoms are located + QHash<QString, xcb_atom_t> ATOMS; + xcb_screen_t *root_screen; + xcb_window_t root_window, wm_window, tray_window; + + //Functions for setting up these objects as needed + bool init_ATOMS(){ + QStringList atoms; + atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW" << "WM_PROTOCOLS" << "WM_CHANGE_STATE" << "_NET_SYSTEM_TRAY_OPCODE" << "_NET_SYSTEM_TRAY_ORIENTATION" << "_NET_SYSTEM_TRAY_VISUAL" << QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())); + //Create all the requests for the atoms + QList<xcb_intern_atom_reply_t*> reply; + for(int i=0; i<atoms.length(); i++){ + reply << xcb_intern_atom_reply(QX11Info::connection(), \ + xcb_intern_atom(QX11Info::connection(), 0, atoms[i].length(), atoms[i].toLocal8Bit()), NULL); + } + //Now evaluate all the requests and save the atoms + for(int i=0; i<reply.length(); i++){ //NOTE: this will always be the same length as the "atoms" list + if(reply[i]!=0){ + obj->ATOMS.insert(atoms[i], reply[i]->atom); + free(reply[i]); //done with this reply + }else{ + //Invalid atom - could not be created + qDebug() << "Could not initialize XCB atom:" << atoms[i]; + } + } //loop over reply + return (obj->ATOMS.keys.length() == atoms.length()); + } + + bool register_wm(){ + uint32_t value_list[1] = {ROOT_WIN_EVENT_MASK}; + xcb_generic_error_t *status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), root_window, XCB_CW_EVENT_MASK, value_list)); + if(status!=0){ return false; } + uint32_t params[] = {1}; + wm_window = xcb_generate_id(QX11Info::connection()); //need a new ID + xcb_create_window(QX11Info::connection(), root_screen->root_depth, \ + win, root_window, -1, -1, 1, 1, 0, \ + XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \ + XCB_CW_OVERRIDE_REDIRECT, params); + if(wm_window==0){ return false; } + //Set the _NET_SUPPORTING_WM property on the root window first + xcb_ewmh_set_supporting_wm_check(&EWMH, root_window, wm_window); + //Also set this property on the child window (pointing to itself) + xcb_ewmh_set_supporting_wm_check(&EWMH, wm_window, wm_window); + //Now also setup the root event mask on the wm_window + status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), wm_window, XCB_CW_EVENT_MASK, value_list)); + if(status!=0){ return false; } + return true; + } + + bool startSystemTray{ + xcb_atom_t _NET_SYSTEM_TRAY_S = ATOMS.value(QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())) ); + //Make sure that there is no other system tray running + xcb_get_selection_owner_reply_t *ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \ + xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL); + if(ownreply==0){ + qWarning() << " - Could not get owner selection reply"; + return false; + }else if(ownreply->owner != 0){ + free(ownreply); + qWarning() << " - An alternate system tray is currently in use"; + return false; + } + free(ownreply); + //Now create the window to use (just offscreen) + //TODO + } + +}; //end private objects class + + +//inline functions for setting up the internal objects + + +// === PUBLIC === +NativeWindowSystem::NativeWindowSystem() : QObject(){ + obj = 0; +} + +NativeWindowSystem::~NativeWindowSystem(){ + xcb_ewmh_connection_wipe(obj->EWMH); + free(obj); +} + +//Overarching start/stop functions +bool NativeWindowSystem::start(){ + //Initialize the XCB/EWMH objects + if(obj==0){ + obj = new p_objects(); } //instantiate the private objects + obj->wm_window = 0; + obj->tray_window = 0; + xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &obj->EWMH); + if(!xcb_ewmh_init_atoms_replies(&obj->EWMH, cookie, NULL) ){ + qDebug() << "Error with XCB atom initializations"; + return false; + } + obj->root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen()); + obj->root_window = obj->root_screen->root; //simplification for later - minor duplication of memory (unsigned int) + //Initialize all the extra atoms that the EWMH object does not have + if( !obj->init_ATOMS() ){ return false; } + } //Done with private object init + + return true; +} + +void NativeWindowSystem::stop(){ + +} + +// === PRIVATE === +void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props){ + +} + +// === PUBLIC SLOTS === +//These are the slots which are only used by the desktop system itself or the NativeWindowEventFilter +void NativeWindowSystem::RegisterVirtualRoot(WId){ + +} + +//NativeWindowEventFilter interactions +void NativeWindowSystem::NewWindowDetected(WId){ + +} + +void NativeWindowSystem::WindowCloseDetected(WId){ + +} + +void NativeWindowSystem::WindowPropertyChanged(WId, NativeWindow::Property){ + +} + +void NativeWindowSystem::NewKeyPress(int keycode){ + +} + +void NativeWindowSystem::NewKeyRelease(int keycode){ + +} + +void NativeWindowSystem::NewMousePress(int buttoncode){ + +} + +void NativeWindowSystem::NewMouseRelease(int buttoncode){ + +} + +// === PRIVATE SLOTS === +//These are the slots which are built-in and automatically connected when a new NativeWindow is created +void NativeWindowSystem::RequestActivate(WId){ + +} +void NativeWindowSystem::RequestClose(WId){ + +} + +void NativeWindowSystem::RequestSetVisible(WId, bool){ + +} +void NativeWindowSystem::RequestSetGeometry(WId, QRect){ + +} +void NativeWindowSystem::RequestSetFrameExtents(WId, QList<int>){ + //[Left,Top,Right,Bottom] in pixels + +} diff --git a/src-qt5/core/libLumina/NativeWindowSystem.h b/src-qt5/core/libLumina/NativeWindowSystem.h new file mode 100644 index 00000000..ef169059 --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindowSystem.h @@ -0,0 +1,92 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is a Qt5/Lumina wrapper around native graphics system calls +// It is primarily designed around the creation/modification of instances of +// the "NativeWindow" class for passing information around +//=========================================== +#ifndef _LUMINA_NATIVE_WINDOW_SYSTEM_H +#define _LUMINA_NATIVE_WINDOW_SYSTEM_H + +#include "NativeWindow.h" + +class NativeWindowSystem : public QObject{ + Q_OBJECT +private: + QList<NativeWindow*> NWindows; + QList<NativeWindow*> TWindows; + + //Simplifications to find an already-created window object + NativeWindow* findWindow(WId id){ + for(int i=0; i<NWindows.length(); i++){ + if(id==NWindows[i]->id()){ return NWindows[i]; } + } + } + + NativeWindow* findTrayWindow(WId id){ + for(int i=0; i<TWindows.length(); i++){ + if(id==TWindows[i]->id()){ return TWindows[i]; } + } + } + + //Now define a simple private_objects class so that each implementation + // has a storage container for placing private objects as needed + class p_objects; + p_objects* obj; + + // Since some properties may be easier to update in bulk + // let the native system interaction do them in whatever logical groups are best + void UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props); + +public: + NativeWindowSystem(); + ~NativeWindowSystem(); + + //Overarching start/stop functions + bool start(); + void stop(); + + //General-purpose listing functions + QList<NativeWindow*> currentWindows(){ return NWindows; } + +public slots: + //These are the slots which are typically only used by the desktop system itself or the NativeWindowEventFilter + + //RootWindow interactions + void RegisterVirtualRoot(WId); + //void GoToWorkspace(int); + //void RegisterWorkspaces(QStringList); //Names of workspaces, in ascending order + //void RegisterKnownInteractions(); + + + //NativeWindowEventFilter interactions + void NewWindowDetected(WId); //will automatically create the new NativeWindow object + void WindowCloseDetected(WId); //will update the lists and make changes if needed + void WindowPropertyChanged(WId, NativeWindow::Property); //will rescan the window and update the object as needed + void NewKeyPress(int keycode); + void NewKeyRelease(int keycode); + void NewMousePress(int buttoncode); + void NewMouseRelease(int buttoncode); + void CheckDamageID(WId); + +private slots: + //These are the slots which are built-in and automatically connected when a new NativeWindow is created + void RequestActivate(WId); + void RequestClose(WId); + void RequestSetVisible(WId, bool); + void RequestSetGeometry(WId, QRect); + void RequestSetFrameExtents(WId, QList<int>); //[Left,Right,Top,Bottom] in pixels + +signals: + void NewWindowAvailable(NativeWindow*); + void NewInputEvent(); //a mouse or keypress was detected (lock-state independent); + void NewKeyPress(int); //only emitted if lockstate = false + void NewKeyRelease(int); //only emitted if lockstate = false + void NewMousePress(Qt::MouseButton); //only emitted if lockstate = false + +}; + +#endif diff --git a/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp b/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp index 27e94737..7031f3df 100644 --- a/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp @@ -53,6 +53,7 @@ void EventFilter::start(){ XCB->setupEventsForRoot(WMFlag); XCB->WM_Set_Supporting_WM(WMFlag); + XCB->WM_Set_Root_Supported(); //announce all the various options that the WM supports static_cast<XCBEventFilter*>(EF)->startSystemTray(); QCoreApplication::instance()->flush(); @@ -482,6 +483,18 @@ void XCBEventFilter::ParsePropertyEvent(xcb_property_notify_event_t *ev){ }else if(ev->atom == obj->XCB->EWMH._NET_WM_ICON){ qDebug() << " - Found _NET_WM_ICON atom"; nwin->setProperty(NativeWindow::Icon, obj->XCB->WM_Get_Icon(nwin->id())); + }else if(ev->atom == obj->XCB->EWMH._NET_WM_ICON_NAME){ + qDebug() << " - Found _NET_WM_ICON_NAME atom"; + nwin->setProperty(NativeWindow::ShortTitle, obj->XCB->WM_Get_Icon_Name(nwin->id())); + }else if(ev->atom == obj->XCB->EWMH._NET_WM_DESKTOP){ + qDebug() << " - Found _NET_WM_DESKTOP atom"; + nwin->setProperty(NativeWindow::Workspace, obj->XCB->WM_Get_Desktop(nwin->id())); + }else if(ev->atom == obj->XCB->EWMH._NET_WM_WINDOW_TYPE ){ + qDebug() << " - Found _NET_WM_WINDOW_TYPE atom"; + + }else if( ev->atom == obj->XCB->EWMH._NET_WM_STATE){ + qDebug() << " - Found _NET_WM_STATE atom"; + } } diff --git a/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp b/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp index 18126dfa..75e4affc 100644 --- a/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp +++ b/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp @@ -325,8 +325,9 @@ void LDesktopPluginSpace::reloadPlugins(bool ForceIconUpdate ){ void LDesktopPluginSpace::paintEvent(QPaintEvent*ev){ if(!wallpaper.isNull()){ QPainter painter(this); - painter.setBrush(wallpaper); - painter.drawRect(ev->rect().adjusted(-1,-1,2,2)); + //painter.setBrush(wallpaper); + //painter.drawRect(ev->rect().adjusted(-1,-1,2,2)); + painter.drawPixmap(ev->rect(), wallpaper, ev->rect() ); }else{ QWidget::paintEvent(ev); } diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp index 0dd68bb0..ab4e786f 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp @@ -16,7 +16,6 @@ LTaskButton::LTaskButton(QWidget *parent, bool smallDisplay) : LTBWidget(parent) winMenu = new QMenu(this); UpdateMenus(); showText = !smallDisplay; - this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setAutoRaise(false); //make sure these always look like buttons this->setContextMenuPolicy(Qt::CustomContextMenu); this->setFocusPolicy(Qt::NoFocus); @@ -126,16 +125,15 @@ void LTaskButton::UpdateButton(){ QString txt = WINLIST[0].text(); if(txt.length()>30){ txt.truncate(27); txt.append("..."); } else if(txt.length()<30){ txt = txt.leftJustified(30, ' '); } - this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText(txt); - }else if(noicon){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( cname ); } - else{ this->setToolButtonStyle(Qt::ToolButtonIconOnly); this->setText(""); } + this->setText(txt); + }else if(noicon){ this->setText( cname ); } + else{ this->setText(""); } this->setToolTip(WINLIST[0].text()); }else if(WINLIST.length() > 1){ //multiple windows this->setPopupMode(QToolButton::InstantPopup); this->setMenu(winMenu); - this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - if(noicon || showText){ "("+QString::number(WINLIST.length())+") "+cname; } + if(noicon || showText){ this->setText("("+QString::number(WINLIST.length())+") "+cname); } else{ this->setText("("+QString::number(WINLIST.length())+")"); } } this->setState(showstate); //Make sure this is after the button setup so that it properly sets the margins/etc diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp index 79c5dd36..c8e24702 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp @@ -116,8 +116,10 @@ void LTaskManagerPlugin::UpdateButtons(){ but->addWindow( winlist[i] ); if(this->layout()->direction()==QBoxLayout::LeftToRight){ but->setIconSize(QSize(this->height(), this->height())); + but->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); }else{ but->setIconSize(QSize(this->width(), this->width())); + but->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); } this->layout()->addWidget(but); connect(but, SIGNAL(MenuClosed()), this, SIGNAL(MenuClosed())); diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp index e465cdf8..2972550c 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp @@ -42,6 +42,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ connect(ui->actionAdd_Dirs, SIGNAL(triggered()), this, SLOT(addDirs()) ); connect(ui->tree_contents, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(ViewFile(QTreeWidgetItem*)) ); connect(ui->actionUSB_Image, SIGNAL(triggered()), this, SLOT(BurnImgToUSB()) ); + connect(ui->tree_contents, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged()) ); //Set Keyboard Shortcuts ui->action_New->setShortcut(tr("CTRL+N")); @@ -88,7 +89,7 @@ void MainUI::loadIcons(){ ui->actionAdd_Dirs->setIcon( LXDG::findIcon("archive-insert-directory","") ); ui->actionRemove_File->setIcon( LXDG::findIcon("archive-remove","") ); ui->actionExtract_All->setIcon( LXDG::findIcon("archive-extract","") ); - ui->actionExtract_Sel->setIcon( LXDG::findIcon("archive-extract","") ); + ui->actionExtract_Sel->setIcon( LXDG::findIcon("edit-select-all","") ); ui->actionUSB_Image->setIcon( LXDG::findIcon("drive-removable-media-usb-pendrive","drive-removable-media-usb") ); } @@ -112,6 +113,12 @@ QTreeWidgetItem* MainUI::findItem(QString path, QTreeWidgetItem *start){ } bool MainUI::cleanItems(QStringList list, QTreeWidgetItem *start){ + //Quick detection for an empty list + if(list.isEmpty() && ui->tree_contents->topLevelItemCount()>0){ + ui->tree_contents->clear(); + return true; + } + //Recursive resolution of items bool changed = false; if(start==0){ for(int i=0; i<ui->tree_contents->topLevelItemCount(); i++){ @@ -154,7 +161,7 @@ QString MainUI::CreateFileTypes(){ QString MainUI::OpenFileTypes(){ QStringList types; - types << QString(tr("All Types %1")).arg("(*.tar.gz *.tar.xz *.tar.bz *.tar.bz2 *.tar.lzma *.tar *.zip *.tgz *.txz *.tbz *.tbz2 *.tlz *.cpio *.pax *.ar *.shar *.7z *.iso *.img *.xar *.jar *.rpm)"); + types << QString(tr("All Known Types %1")).arg("(*.tar.gz *.tar.xz *.tar.bz *.tar.bz2 *.tar.lzma *.tar *.zip *.tgz *.txz *.tbz *.tbz2 *.tlz *.cpio *.pax *.ar *.shar *.7z *.iso *.img *.xar *.jar *.rpm)"); types << tr("Uncompressed Archive (*.tar)"); types << tr("GZip Compressed Archive (*.tar.gz *.tgz)"); types << tr("BZip Compressed Archive (*.tar.bz *.tbz)"); @@ -171,6 +178,7 @@ QString MainUI::OpenFileTypes(){ types << tr("READ-ONLY: XAR archive (*.xar)"); types << tr("READ-ONLY: Java archive (*.jar)"); types << tr("READ-ONLY: RedHat Package (*.rpm)"); + types << tr("Show All Files (*)"); return types.join(";;"); } @@ -340,7 +348,8 @@ void MainUI::ProcFinished(bool success, QString msg){ canmodify = canmodify && BACKEND->canModify(); //also include the file type limitations ui->actionAdd_File->setEnabled(canmodify); ui->actionRemove_File->setEnabled(canmodify && info.exists()); - ui->actionExtract_All->setEnabled(info.exists()); + ui->actionExtract_All->setEnabled(info.exists() && ui->tree_contents->topLevelItemCount()>0); + ui->actionExtract_Sel->setEnabled(info.exists() && !ui->tree_contents->selectedItems().isEmpty()); ui->actionAdd_Dirs->setEnabled(canmodify); } @@ -349,3 +358,7 @@ void MainUI::ProcUpdate(int percent, QString txt){ ui->progressBar->setValue(percent); if(!txt.isEmpty()){ ui->label_progress->setText(txt); } } + +void MainUI::selectionChanged(){ + ui->actionExtract_Sel->setEnabled(!ui->tree_contents->selectedItems().isEmpty()); +} diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.h b/src-qt5/desktop-utils/lumina-archiver/MainUI.h index bf37d26a..273078ea 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.h +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.h @@ -55,6 +55,8 @@ private slots: void ProcFinished(bool, QString); void ProcUpdate(int percent, QString txt); + //UI Slots + void selectionChanged(); }; #endif diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.ui b/src-qt5/desktop-utils/lumina-archiver/MainUI.ui index 6666b7cb..0fc9eadf 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.ui @@ -15,6 +15,15 @@ </property> <widget class="QWidget" name="centralwidget"> <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>3</number> + </property> + <property name="topMargin"> + <number>1</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> @@ -111,7 +120,7 @@ <x>0</x> <y>0</y> <width>403</width> - <height>22</height> + <height>20</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -168,6 +177,7 @@ <addaction name="actionRemove_File"/> <addaction name="separator"/> <addaction name="actionExtract_All"/> + <addaction name="actionExtract_Sel"/> </widget> <action name="action_Open"> <property name="text"> @@ -226,6 +236,9 @@ <property name="text"> <string>Extract Selection</string> </property> + <property name="statusTip"> + <string>Extract Selected Items</string> + </property> </action> <action name="actionUSB_Image"> <property name="text"> diff --git a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp index 78efd51c..0659f8b1 100644 --- a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp @@ -27,6 +27,7 @@ Backend::~Backend(){ // PUBLIC //=============== void Backend::loadFile(QString path){ + //qDebug() << "Loading Archive:" << path; filepath = path; tmpfilepath = filepath.section("/",0,-2)+"/"+".tmp_larchiver_"+filepath.section("/",-1); flags.clear(); @@ -149,7 +150,7 @@ void Backend::startViewFile(QString path){ args << "-x"; args << flags <<"--include" << path <<"--strip-components" << QString::number(path.count("/")) << "-C" << QDir::tempPath(); STARTING=true; - qDebug() << "Starting command:" << "tar" << args; + //qDebug() << "Starting command:" << "tar" << args; PROC.start("tar", args); } @@ -195,6 +196,7 @@ void Backend::startList(){ QStringList args; args << "-tv"; LIST = STARTING=true; + //qDebug() << "Starting List:" << "tar "+args.join(" ")+" "+flags.join(" "); PROC.start("tar", QStringList() << args << flags); } @@ -203,12 +205,17 @@ void Backend::startList(){ //=============== void Backend::procFinished(int retcode, QProcess::ExitStatus){ static QString result; - processData(); //qDebug() << "Process Finished:" << PROC.arguments() << retcode; + processData(); LIST = STARTING = false; if(PROC.arguments().contains("-tv")){ - if(retcode!=0){ contents.clear(); } //could not read archive - emit ProcessFinished(true,result); + if(retcode!=0){ //could not read archive + contents.clear(); + result = tr("Could not read archive"); + }else if(result.isEmpty()){ + result = tr("Archive Loaded"); + } + emit ProcessFinished((retcode==0), result); result.clear(); }else{ bool needupdate = true; diff --git a/src-qt5/desktop-utils/lumina-screenshot/MainUI.cpp b/src-qt5/desktop-utils/lumina-screenshot/MainUI.cpp index 40c9857b..2c5dc700 100644 --- a/src-qt5/desktop-utils/lumina-screenshot/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-screenshot/MainUI.cpp @@ -9,7 +9,7 @@ #include <LuminaX11.h> #include <QMessageBox> - +#include <QClipboard> MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ ui->setupUi(this); //load the designer file @@ -30,7 +30,8 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ scaleTimer->setSingleShot(true); scaleTimer->setInterval(200); //~1/5 second tabbar = new QTabBar(this); - ui->tabLayout->insertWidget(0,tabbar); + tabbar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + ui->tabLayout->insertWidget(0,tabbar, Qt::AlignLeft | Qt::AlignBottom); tabbar->addTab(LXDG::findIcon("view-preview",""), tr("View")); tabbar->addTab(LXDG::findIcon("preferences-other",""), tr("Settings")); ui->stackedWidget->setCurrentWidget(ui->page_current); @@ -47,6 +48,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ //connect(ui->push_snap, SIGNAL(clicked()), this, SLOT(startScreenshot()) ); connect(ui->actionTake_Screenshot, SIGNAL(triggered()), this, SLOT(startScreenshot()) ); connect(ui->tool_crop, SIGNAL(clicked()), IMG, SLOT(cropImage()) ); + connect(ui->tool_copy_to_clipboard, SIGNAL(clicked()), this, SLOT(copyToClipboard()) ); connect(IMG, SIGNAL(selectionChanged(bool)), this, SLOT(imgselchanged(bool)) ); connect(IMG, SIGNAL(scaleFactorChanged(int)), this, SLOT(imgScalingChanged(int)) ); connect(ui->slider_zoom, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged()) ); @@ -74,16 +76,14 @@ MainUI::~MainUI(){} void MainUI::setupIcons(){ //Setup the icons - //ui->tool_save->setIcon( LXDG::findIcon("document-save","") ); ui->tool_quicksave->setIcon( LXDG::findIcon("document-edit","") ); ui->actionSave_As->setIcon( LXDG::findIcon("document-save-as","") ); ui->actionQuick_Save->setIcon( LXDG::findIcon("document-save","") ); ui->actionClose->setIcon( LXDG::findIcon("application-exit","") ); - //ui->push_snap->setIcon( LXDG::findIcon("camera-web","") ); + ui->tool_copy_to_clipboard->setIcon( LXDG::findIcon("insert-image","") ); ui->actionTake_Screenshot->setIcon( LXDG::findIcon("camera-web","") ); ui->tool_crop->setIcon( LXDG::findIcon("transform-crop","") ); ui->tool_resize->setIcon( LXDG::findIcon("transform-scale","") ); - //ui->actionEdit->setIcon( LXDG::findIcon("applications-graphics","") ); this->setWindowIcon( LXDG::findIcon("camera-web","") ); } @@ -121,6 +121,12 @@ void MainUI::quicksave(){ } } +void MainUI::copyToClipboard(){ + qDebug() << "Copy Image to clipboard"; + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setImage(IMG->image()); + qDebug() << " - Success:" << !clipboard->image().isNull(); +} void MainUI::startScreenshot(){ if(mousegrabbed){ return; } diff --git a/src-qt5/desktop-utils/lumina-screenshot/MainUI.h b/src-qt5/desktop-utils/lumina-screenshot/MainUI.h index 396bfafe..5ff496a5 100644 --- a/src-qt5/desktop-utils/lumina-screenshot/MainUI.h +++ b/src-qt5/desktop-utils/lumina-screenshot/MainUI.h @@ -63,6 +63,7 @@ private slots: } void saveScreenshot(); void quicksave(); + void copyToClipboard(); void startScreenshot(); diff --git a/src-qt5/desktop-utils/lumina-screenshot/MainUI.ui b/src-qt5/desktop-utils/lumina-screenshot/MainUI.ui index cddee009..0c70d3d8 100644 --- a/src-qt5/desktop-utils/lumina-screenshot/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-screenshot/MainUI.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>386</width> - <height>288</height> + <width>480</width> + <height>318</height> </rect> </property> <property name="sizePolicy"> @@ -54,7 +54,7 @@ <item> <widget class="QFrame" name="frame_modify"> <property name="frameShape"> - <enum>QFrame::NoFrame</enum> + <enum>QFrame::StyledPanel</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> @@ -83,12 +83,44 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="statusTip"> + <string>Open screenshot with an application</string> + </property> <property name="text"> - <string>Open With...</string> + <string>Open</string> </property> <property name="toolButtonStyle"> <enum>Qt::ToolButtonTextBesideIcon</enum> </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_copy_to_clipboard"> + <property name="statusTip"> + <string>Copy screenshot to clipboard</string> + </property> + <property name="text"> + <string>Copy</string> + </property> + <property name="shortcut"> + <string>Ctrl+C</string> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> </widget> </item> <item> @@ -99,12 +131,18 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="statusTip"> + <string>Resize screenshot to selection</string> + </property> <property name="text"> <string>Resize</string> </property> <property name="toolButtonStyle"> <enum>Qt::ToolButtonTextBesideIcon</enum> </property> + <property name="autoRaise"> + <bool>true</bool> + </property> </widget> </item> <item> @@ -115,12 +153,18 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="statusTip"> + <string>Crop screenshot to selection</string> + </property> <property name="text"> <string>&Crop</string> </property> <property name="toolButtonStyle"> <enum>Qt::ToolButtonTextBesideIcon</enum> </property> + <property name="autoRaise"> + <bool>true</bool> + </property> </widget> </item> </layout> @@ -210,8 +254,8 @@ <rect> <x>0</x> <y>0</y> - <width>344</width> - <height>216</height> + <width>439</width> + <height>230</height> </rect> </property> </widget> @@ -466,6 +510,7 @@ <addaction name="actionQuick_Save"/> <addaction name="actionClose"/> </widget> + <widget class="QStatusBar" name="statusBar"/> <action name="actionTake_Screenshot"> <property name="text"> <string>Capture</string> |