aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/src-cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/src-cpp')
-rw-r--r--src-qt5/src-cpp/NativeEventFilter.cpp300
-rw-r--r--src-qt5/src-cpp/NativeEventFilter.h71
-rw-r--r--src-qt5/src-cpp/NativeKeyToQt.cpp528
-rw-r--r--src-qt5/src-cpp/NativeWindowSystem.cpp986
-rw-r--r--src-qt5/src-cpp/NativeWindowSystem.h139
-rw-r--r--src-qt5/src-cpp/framework-OSInterface-FreeBSD.cpp245
-rw-r--r--src-qt5/src-cpp/framework-OSInterface-template.cpp168
-rw-r--r--src-qt5/src-cpp/framework-OSInterface.h170
-rw-r--r--src-qt5/src-cpp/framework-OSInterface.pri15
-rw-r--r--src-qt5/src-cpp/framework-OSInterface_private.cpp605
-rw-r--r--src-qt5/src-cpp/plugins-base.h6
-rw-r--r--src-qt5/src-cpp/plugins-desktop.cpp36
-rw-r--r--src-qt5/src-cpp/plugins-desktop.h6
-rw-r--r--src-qt5/src-cpp/tests/main.cpp3
14 files changed, 1103 insertions, 2175 deletions
diff --git a/src-qt5/src-cpp/NativeEventFilter.cpp b/src-qt5/src-cpp/NativeEventFilter.cpp
deleted file mode 100644
index c13c1fc8..00000000
--- a/src-qt5/src-cpp/NativeEventFilter.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-//===========================================
-// Lumina-desktop source code
-// Copyright (c) 2015-2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-#include "NativeEventFilter.h"
-#include <QCoreApplication>
-#include <QDebug>
-
-//#include <xcb/xcb_aux.h>
-//#include <xcb/damage.h>
-
-//==================================================
-// NOTE: All the XCB interactions and atoms are accessed via:
-// obj->XCB->EWMH.(atom name)
-// obj->XCB->(do something)
-//==================================================
-
-/*
-List of XCB response types (since almost impossible to find good docs on XCB)
-switch (xcb_generic_event_t*->response_type & ~0x80)
-case values:
-XCB_KEY_[PRESS | RELEASE]
-XCB_BUTTON_[PRESS | RELEASE]
-XCB_MOTION_NOTIFY
-XCB_ENTER_NOTIFY
-XCB_LEAVE_NOTIFY
-XCB_FOCUS_[IN | OUT]
-XCB_KEYMAP_NOTIFY
-XCB_EXPOSE
-XCB_GRAPHICS_EXPOSURE
-XCB_VISIBILITY_NOTIFY
-XCB_CREATE_NOTIFY
-XCB_DESTROY_NOTIFY
-XCB_UNMAP_NOTIFY
-XCB_MAP_[NOTIFY | REQUEST]
-XCB_REPARENT_NOTIFY
-XCB_CONFIGURE_[NOTIFY | REQUEST]
-XCB_GRAVITY_NOTIFY
-XCB_RESIZE_REQUEST
-XCB_CIRCULATE_[NOTIFY | REQUEST]
-XCB_PROPERTY_NOTIFY
-XCB_SELECTION_[CLEAR | REQUEST | NOTIFY]
-XCB_COLORMAP_NOTIFY
-XCB_CLIENT_MESSAGE
-*/
-
-//SYSTEM TRAY STANDARD DEFINITIONS
-#define SYSTEM_TRAY_REQUEST_DOCK 0
-#define SYSTEM_TRAY_BEGIN_MESSAGE 1
-#define SYSTEM_TRAY_CANCEL_MESSAGE 2
-
-//#include <LuminaX11.h>
-#include <QX11Info>
-#include <xcb/xcb_ewmh.h>
-#include <xcb/xcb_keysyms.h>
-#include <xcb/damage.h>
-
-#define DEBUG 0
-
-//Special objects/variables for XCB parsing
-static xcb_ewmh_connection_t EWMH;
-//static LXCB *XCB = 0;
-static xcb_atom_t _NET_SYSTEM_TRAY_OPCODE = 0;
-
-inline void ParsePropertyEvent(xcb_property_notify_event_t *ev, NativeEventFilter *obj){
- //qDebug() << "Got Property Event:" << ev->window << ev->atom;
- NativeWindow::Property prop = NativeWindow::None;
- //Now determine which properties are getting changed, and update the native window as appropriate
- if(ev->atom == EWMH._NET_WM_NAME){ prop = NativeWindow::Title; }
- else if(ev->atom == EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; }
- else if(ev->atom == EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; }
- else if(ev->atom == EWMH._NET_WM_DESKTOP){ prop = NativeWindow::Workspace; }
- else if(ev->atom == EWMH._NET_WM_WINDOW_TYPE ){ prop = NativeWindow::WinTypes; }
- else if( ev->atom == EWMH._NET_WM_STATE){ prop = NativeWindow::States; }
- //Send out the signal if necessary
- if(prop!=NativeWindow::None){
- //if(DEBUG){
- //qDebug() << "Detected Property Change:" << ev->window << prop;
- //}
- obj->emit WindowPropertyChanged(ev->window, prop);
- }else{
- //Quick re-check of the simple properties (nothing like the icon or other graphics)
- obj->emit WindowPropertiesChanged(ev->window, QList<NativeWindow::Property>() << NativeWindow::Title
- << NativeWindow::ShortTitle << NativeWindow::Workspace );
- //qDebug() << "Unknown Property Change:" << ev->window << ev->atom;
- }
-}
-
-inline void ParseClientMessageEvent(xcb_client_message_event_t *ev, NativeEventFilter *obj){
- NativeWindow::Property prop = NativeWindow::None;
- QVariant val;
- if(ev->type==EWMH._NET_WM_NAME){ prop = NativeWindow::Title; }
- else if(ev->type==EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; }
- else if(ev->type==EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; }
- else if(ev->type==EWMH._NET_WM_DESKTOP){
- prop = NativeWindow::Workspace;
- val = QVariant( (int) ev->data.data32[0] );
- }else if(ev->type==EWMH._NET_WM_WINDOW_TYPE){ prop = NativeWindow::WinTypes; }
- else if(ev->type==EWMH._NET_WM_STATE){ prop = NativeWindow::States; }
-
- if(prop!=NativeWindow::None){
- //if(DEBUG){
- qDebug() << "Detected Property Change Request:" << ev->window << prop; //}
- if(val.isNull()){ obj->emit WindowPropertyChanged(ev->window, prop); }
- else{ obj->emit RequestWindowPropertyChange(ev->window, prop, val); }
- }
-
-}
-
-
-//Constructor for the Event Filter wrapper
-NativeEventFilter::NativeEventFilter() : QObject(){
- EF = new EventFilter(this);
- if(EWMH.nb_screens <=0){
- xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH);
- if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){
- qDebug() << "Error with XCB atom initializations";
- }
- }
- if(_NET_SYSTEM_TRAY_OPCODE==0){
- //_NET_SYSTEM_TRAY_OPCODE
- xcb_intern_atom_cookie_t cookie = xcb_intern_atom(QX11Info::connection(), 0, 23,"_NET_SYSTEM_TRAY_OPCODE");
- xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(QX11Info::connection(), cookie, NULL);
- if(r){
- _NET_SYSTEM_TRAY_OPCODE = r->atom;
- free(r);
- }
- }
-}
-
-void NativeEventFilter::start(){
- if(DEBUG){ qDebug() << " - Install event filter..."; }
- QCoreApplication::instance()->installNativeEventFilter(EF);
- if(DEBUG){ qDebug() << " - Run request check..."; }
-
-}
-
-void NativeEventFilter::stop(){
- QCoreApplication::instance()->installNativeEventFilter(0);
-}
-
-//=============================
-// EventFilter Class
-//=============================
-
-//Constructor for the XCB event filter
-EventFilter::EventFilter(NativeEventFilter *parent) : QAbstractNativeEventFilter(){
- obj = parent;
-}
-
-//This function format taken directly from the Qt5.3 documentation
-bool EventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *){
- //qDebug() << "New Event";
- if(eventType=="xcb_generic_event_t"){
- //Convert to known event type (for X11 systems)
- xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
- //Now parse the event and emit signals as necessary
- switch( ev->response_type & ~0x80){
-//==============================
-// INTERACTIVITY EVENTS
-//==============================
- case XCB_KEY_PRESS:
- //This is a keyboard key press
- //qDebug() << "Key Press Event"
- obj->emit KeyPressed( ((xcb_key_press_event_t *) ev)->detail, ((xcb_key_press_event_t *) ev)->root );
- break;
- case XCB_KEY_RELEASE:
- //This is a keyboard key release
- //qDebug() << "Key Release Event";
- obj->emit KeyReleased( ((xcb_key_release_event_t *) ev)->detail, ((xcb_key_release_event_t *) ev)->root );
- break;
- case XCB_BUTTON_PRESS:
- //This is a mouse button press
- //qDebug() << "Button Press Event";
- obj->emit MousePressed( ((xcb_button_press_event_t *) ev)->detail, ((xcb_button_press_event_t *) ev)->root );
- break;
- case XCB_BUTTON_RELEASE:
- //This is a mouse button release
- //qDebug() << "Button Release Event";
- obj->emit MouseReleased( ((xcb_button_release_event_t *) ev)->detail, ((xcb_button_release_event_t *) ev)->root );
- break;
- case XCB_MOTION_NOTIFY:
- //This is a mouse movement event
- if(DEBUG){ qDebug() << "Motion Notify Event"; }
- obj->emit MouseMovement();
- break;
- case XCB_ENTER_NOTIFY:
- //This is a mouse movement event when mouse goes over a new window
- //qDebug() << "Enter Notify Event";
- obj->emit MouseEnterWindow( ((xcb_enter_notify_event_t *) ev)->root );
- break;
- case XCB_LEAVE_NOTIFY:
- //This is a mouse movement event when mouse goes leaves a window
- //qDebug() << "Leave Notify Event";
- obj->emit MouseLeaveWindow( ((xcb_leave_notify_event_t *) ev)->root );
- break;
-//==============================
- case XCB_EXPOSE:
- //qDebug() << "Expose Notify Event:";
- //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window;
- break;
-//==============================
- case XCB_MAP_NOTIFY:
- //qDebug() << "Window Map Event:" << ((xcb_map_notify_event_t *)ev)->window;
- obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, true);
- break; //This is just a notification that a window was mapped - nothing needs to change here
- case XCB_MAP_REQUEST:
- //qDebug() << "Window Map Request Event";
- obj->emit WindowCreated( ((xcb_map_request_event_t *) ev)->window );
- break;
-//==============================
- case XCB_CREATE_NOTIFY:
- //qDebug() << "Window Create Event";
- break;
-//==============================
- case XCB_UNMAP_NOTIFY:
- //qDebug() << "Window Unmap Event:" << ((xcb_unmap_notify_event_t *)ev)->window;
- obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, false);
- break;
-//==============================
- case XCB_DESTROY_NOTIFY:
- //qDebug() << "Window Closed Event:" << ((xcb_destroy_notify_event_t *)ev)->window;
- obj->emit WindowDestroyed( ((xcb_destroy_notify_event_t *) ev)->window );
- break;
-//==============================
- case XCB_FOCUS_IN:
- //qDebug() << "Focus In Event:";
- break;
-//==============================
- case XCB_FOCUS_OUT:
- //qDebug() << "Focus Out Event:";
- break;
-//==============================
- case XCB_PROPERTY_NOTIFY:
- //qDebug() << "Property Notify Event:";
- ParsePropertyEvent((xcb_property_notify_event_t*)ev, obj);
- break;
-//==============================
- case XCB_CLIENT_MESSAGE:
- //qDebug() << "Client Message Event";
- //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window;
- if( ((xcb_client_message_event_t*)ev)->type == _NET_SYSTEM_TRAY_OPCODE && ((xcb_client_message_event_t*)ev)->format == 32){
- //data32[0] is timestamp, [1] is opcode, [2] is window handle
- if(SYSTEM_TRAY_REQUEST_DOCK == ((xcb_client_message_event_t*)ev)->data.data32[1]){
- obj->emit TrayWindowCreated( ((xcb_client_message_event_t*)ev)->data.data32[2] );
- //addTrayApp( ((xcb_client_message_event_t*)ev)->data.data32[2] );
- }
- //Ignore the System Tray messages at the moment
- }else if(((xcb_client_message_event_t*)ev)->window != QX11Info::appRootWindow()){
- ParseClientMessageEvent((xcb_client_message_event_t*)ev, obj);
- }
- break;
-//==============================
- case XCB_CONFIGURE_NOTIFY:
- //qDebug() << "Configure Notify Event";
- /*obj->emit WindowPropertiesChanged( ((xcb_configure_notify_event_t*)ev)->window,
- QList<NativeWindow::Property>() << NativeWindow::GlobalPos << NativeWindow::Size,
- QList<QVariant>() << QPoint(((xcb_configure_notify_event_t*)ev)->x, ((xcb_configure_notify_event_t*)ev)->y) <<
- QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) );*/
- obj->emit WindowPropertyChanged( ((xcb_configure_notify_event_t*)ev)->window, NativeWindow::Size,
- QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) );
- break;
-//==============================
- case XCB_CONFIGURE_REQUEST:
- //qDebug() << "Configure Request Event";
- obj->emit RequestWindowPropertiesChange( ((xcb_configure_request_event_t*)ev)->window,
- QList<NativeWindow::Property>() << NativeWindow::GlobalPos << NativeWindow::Size,
- QList<QVariant>() << QPoint(((xcb_configure_request_event_t*)ev)->x, ((xcb_configure_request_event_t*)ev)->y) <<
- QSize(((xcb_configure_request_event_t*)ev)->width, ((xcb_configure_request_event_t*)ev)->height) );
- break;
-//==============================
- case XCB_RESIZE_REQUEST:
- //qDebug() << "Resize Request Event";
- obj->emit RequestWindowPropertyChange( ((xcb_resize_request_event_t*)ev)->window,
- NativeWindow::Size, QSize(((xcb_resize_request_event_t*)ev)->width, ((xcb_resize_request_event_t*)ev)->height) );
- break;
-//==============================
- case XCB_SELECTION_CLEAR:
- //qDebug() << "Selection Clear Event";
- break;
-//==============================
- case 85: //not sure what event this is - but it seems to come up very often (just hide the notice)
- case 0:
- case XCB_GE_GENERIC:
- break; //generic event - don't do anything special
- default:
- //if( (ev->response_type & ~0x80)==TrayDmgID){
- obj->emit PossibleDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable );
- //checkDamageID( ((xcb_damage_notify_event_t*)ev)->drawable );
- //}else{
- //qDebug() << "Default Event:" << (ev->response_type & ~0x80);
- //}
-//==============================
- }
- }
- return false;
- //never stop event handling (this will not impact the X events themselves - just the internal Qt application)
-}
diff --git a/src-qt5/src-cpp/NativeEventFilter.h b/src-qt5/src-cpp/NativeEventFilter.h
deleted file mode 100644
index a3be3ef1..00000000
--- a/src-qt5/src-cpp/NativeEventFilter.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//===========================================
-// Lumina-DE source code
-// Copyright (c) 2012-2017, Ken Moore
-// Available under the 3-clause BSD license
-// See the LICENSE file for full details
-//===========================================
-// This class provides the XCB event handling/registrations that are needed
-//===========================================
-#ifndef _LUMINA_DESKTOP_NATIVE_EVENT_FILTER_H
-#define _LUMINA_DESKTOP_NATIVE_EVENT_FILTER_H
-
-#include <QAbstractNativeEventFilter>
-#include <QObject>
-#include <QByteArray>
-
-#include "NativeWindow.h"
-
-
-class NativeEventFilter : public QObject{
- Q_OBJECT
-private:
- QAbstractNativeEventFilter* EF;
- WId WMFlag; //used to flag a running WM process
-
-public:
- NativeEventFilter();
- ~NativeEventFilter(){}
-
- void start();
- void stop();
-
-signals:
- //Window Signals
- void WindowCreated(WId);
- void WindowDestroyed(WId);
- void WindowPropertyChanged(WId, NativeWindow::Property);
- void WindowPropertiesChanged(WId, QList<NativeWindow::Property>);
- void WindowPropertyChanged(WId, NativeWindow::Property, QVariant);
- void WindowPropertiesChanged(WId, QList<NativeWindow::Property>, QList<QVariant>);
- void RequestWindowPropertyChange(WId, NativeWindow::Property, QVariant);
- void RequestWindowPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>);
-
- //System Tray Signals
- void TrayWindowCreated(WId);
- void TrayWindowDestroyed(WId);
-
- //Miscellaneos Signals
- void PossibleDamageEvent(WId);
-
- //Input Event Signals
- void KeyPressed(int, WId);
- void KeyReleased(int, WId);
- void MousePressed(int, WId);
- void MouseReleased(int, WId);
- void MouseMovement();
- void MouseEnterWindow(WId);
- void MouseLeaveWindow(WId);
-};
-
-class EventFilter : public QAbstractNativeEventFilter{
-public:
- EventFilter(NativeEventFilter *parent);
- ~EventFilter(){}
-
- virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *);
-
-private:
- NativeEventFilter *obj;
-};
-
-#endif
diff --git a/src-qt5/src-cpp/NativeKeyToQt.cpp b/src-qt5/src-cpp/NativeKeyToQt.cpp
deleted file mode 100644
index 06056be7..00000000
--- a/src-qt5/src-cpp/NativeKeyToQt.cpp
+++ /dev/null
@@ -1,528 +0,0 @@
-
-#include <NativeWindowSystem.h>
-
-#include <QKeySequence>
-#include <QX11Info>
-
-// XCB/X11 Includes
-#define XK_MISCELLANY
-#define XK_XKB_KEYS
-#define XK_LATIN1
-#define XK_LATIN2
-#define XK_LATIN3
-#define XK_LATIN4
-#define XK_LATIN8
-#define XK_LATIN9
-//NOTE: Look at the keysymdef.h file for additional define/characters which we may need later
-#include <X11/keysymdef.h>
-#include <xcb/xcb_keysyms.h>
-
-
-//Small simplification functions
-Qt::Key NativeWindowSystem::KeycodeToQt(int keycode){
- static xcb_key_symbols_t *SYM = 0;
- if(SYM==0){ SYM = xcb_key_symbols_alloc(QX11Info::connection()); }
- xcb_keysym_t symbol = xcb_key_symbols_get_keysym(SYM, keycode,0);
- //not sure about the "column" input - we want raw keys though so ignore the "modified" key states (columns) for now
- //qDebug() << "Try to convert keycode to Qt::Key:" << keycode << symbol;
- //Now map this symbol to the appropriate Qt::Key enumeration
- switch(symbol){
- //FUNCTION KEYS
- case XK_F1: return Qt::Key_F1;
- case XK_F2: return Qt::Key_F2;
- case XK_F3: return Qt::Key_F3;
- case XK_F4: return Qt::Key_F4;
- case XK_F5: return Qt::Key_F5;
- case XK_F6: return Qt::Key_F6;
- case XK_F7: return Qt::Key_F7;
- case XK_F8: return Qt::Key_F8;
- case XK_F9: return Qt::Key_F9;
- case XK_F10: return Qt::Key_F10;
- case XK_F11: return Qt::Key_F11;
- case XK_F12: return Qt::Key_F12;
- case XK_F13: return Qt::Key_F13;
- case XK_F14: return Qt::Key_F14;
- case XK_F15: return Qt::Key_F15;
- case XK_F16: return Qt::Key_F16;
- case XK_F17: return Qt::Key_F17;
- case XK_F18: return Qt::Key_F18;
- case XK_F19: return Qt::Key_F19;
- case XK_F20: return Qt::Key_F20;
- case XK_F21: return Qt::Key_F21;
- case XK_F22: return Qt::Key_F22;
- case XK_F23: return Qt::Key_F23;
- case XK_F24: return Qt::Key_F24;
- case XK_F25: return Qt::Key_F25;
- case XK_F26: return Qt::Key_F26;
- case XK_F27: return Qt::Key_F27;
- case XK_F28: return Qt::Key_F28;
- case XK_F29: return Qt::Key_F29;
- case XK_F30: return Qt::Key_F30;
- case XK_F31: return Qt::Key_F31;
- case XK_F32: return Qt::Key_F32;
- case XK_F33: return Qt::Key_F33;
- case XK_F34: return Qt::Key_F34;
- case XK_F35: return Qt::Key_F35;
- //Miscellaneous Keys
- case XK_BackSpace: return Qt::Key_Backspace;
- case XK_Delete: return Qt::Key_Delete;
- //case XK_LineFeed: return Qt::Key_Backspace;
- case XK_Clear: return Qt::Key_Clear;
- case XK_Return: return Qt::Key_Return;
- case XK_Pause: return Qt::Key_Pause;
- case XK_Scroll_Lock: return Qt::Key_ScrollLock;
- case XK_Sys_Req: return Qt::Key_SysReq;
- case XK_Escape: return Qt::Key_Escape;
- case XK_Select: return Qt::Key_Select;
- case XK_Print: return Qt::Key_Print;
- //case XK_Execute: return Qt::Key_Execute;
- case XK_Insert: return Qt::Key_Insert;
- case XK_Undo: return Qt::Key_Undo;
- case XK_Redo: return Qt::Key_Redo;
- case XK_Menu: return Qt::Key_Menu;
- case XK_Find: return Qt::Key_Find;
- case XK_Cancel: return Qt::Key_Cancel;
- case XK_Help: return Qt::Key_Help;
- //case XK_Break: return Qt::Key_Break;
- //case XK_Mode_switch: return Qt::Key_Backspace;
- //case XK_script_switch: return Qt::Key_Backspace;
- case XK_Num_Lock: return Qt::Key_NumLock;
- //Cursor Controls
- case XK_Home: return Qt::Key_Home;
- case XK_Left: return Qt::Key_Left;
- case XK_Up: return Qt::Key_Up;
- case XK_Right: return Qt::Key_Right;
- case XK_Down: return Qt::Key_Down;
- //case XK_Prior: return Qt::Key_Backspace;
- case XK_Page_Up: return Qt::Key_PageUp;
- case XK_Page_Down: return Qt::Key_PageDown;
- //case XK_Next: return Qt::Key_Backspace;
- case XK_End: return Qt::Key_End;
- //case XK_Begin: return Qt::Key_Backspace;
- // Keypad Functions and numbers
- case XK_KP_Space: return Qt::Key_Space;
- case XK_KP_Tab: return Qt::Key_Tab;
- case XK_KP_Enter: return Qt::Key_Enter;
- case XK_KP_F1: return Qt::Key_F1;
- case XK_KP_F2: return Qt::Key_F2;
- case XK_KP_F3: return Qt::Key_F3;
- case XK_KP_F4: return Qt::Key_F4;
- case XK_KP_Home: return Qt::Key_Home;
- case XK_KP_Left: return Qt::Key_Left;
- case XK_KP_Up: return Qt::Key_Up;
- case XK_KP_Right: return Qt::Key_Right;
- case XK_KP_Down: return Qt::Key_Down;
- //case XK_KP_Prior: return Qt::Key_
- case XK_KP_Page_Up: return Qt::Key_PageUp;
- //case XK_KP_Next: return Qt::Key_
- case XK_KP_Page_Down: return Qt::Key_PageDown;
- case XK_KP_End: return Qt::Key_End;
- //case XK_KP_Begin: return Qt::Key_
- case XK_KP_Insert: return Qt::Key_Insert;
- case XK_KP_Delete: return Qt::Key_Delete;
- case XK_KP_Equal: return Qt::Key_Equal;
- case XK_KP_Multiply: return Qt::Key_Asterisk;
- case XK_KP_Add: return Qt::Key_Plus;
- case XK_KP_Separator: return Qt::Key_Comma; //X11 definitions say this is often comma
- case XK_KP_Subtract: return Qt::Key_Minus;
- case XK_KP_Decimal: return Qt::Key_Period;
- case XK_KP_Divide: return Qt::Key_Slash;
- case XK_KP_0: return Qt::Key_0;
- case XK_KP_1: return Qt::Key_1;
- case XK_KP_2: return Qt::Key_2;
- case XK_KP_3: return Qt::Key_3;
- case XK_KP_4: return Qt::Key_4;
- case XK_KP_5: return Qt::Key_5;
- case XK_KP_6: return Qt::Key_6;
- case XK_KP_7: return Qt::Key_7;
- case XK_KP_8: return Qt::Key_8;
- case XK_KP_9: return Qt::Key_9;
- // Modifier Keys
- case XK_Shift_L: return Qt::Key_Shift;
- case XK_Shift_R: return Qt::Key_Shift;
- case XK_Control_L: return Qt::Key_Control;
- case XK_Control_R: return Qt::Key_Control;
- case XK_Caps_Lock: return Qt::Key_CapsLock;
- //case XK_Shift_Lock: return Qt::Key_ShiftLock;
- case XK_Meta_L: return Qt::Key_Meta;
- case XK_Meta_R: return Qt::Key_Meta;
- case XK_Alt_L: return Qt::Key_Alt;
- case XK_Alt_R: return Qt::Key_Alt;
- case XK_Super_L: return Qt::Key_Super_L;
- case XK_Super_R: return Qt::Key_Super_R;
- case XK_Hyper_L: return Qt::Key_Hyper_L;
- case XK_Hyper_R: return Qt::Key_Hyper_R;
- case XK_space: return Qt::Key_Space;
- case XK_exclam: return Qt::Key_Exclam;
- case XK_quotedbl: return Qt::Key_QuoteDbl;
- case XK_numbersign: return Qt::Key_NumberSign;
- case XK_dollar: return Qt::Key_Dollar;
- case XK_percent: return Qt::Key_Percent;
- case XK_ampersand: return Qt::Key_Ampersand;
- case XK_apostrophe: return Qt::Key_Apostrophe;
- case XK_parenleft: return Qt::Key_ParenLeft;
- case XK_parenright: return Qt::Key_ParenRight;
- case XK_asterisk: return Qt::Key_Asterisk;
- case XK_plus: return Qt::Key_Plus;
- case XK_comma: return Qt::Key_Comma;
- case XK_minus: return Qt::Key_Minus;
- case XK_period: return Qt::Key_Period;
- case XK_slash: return Qt::Key_Slash;
- case XK_0: return Qt::Key_0;
- case XK_1: return Qt::Key_1;
- case XK_2: return Qt::Key_2;
- case XK_3: return Qt::Key_3;
- case XK_4: return Qt::Key_4;
- case XK_5: return Qt::Key_5;
- case XK_6: return Qt::Key_6;
- case XK_7: return Qt::Key_7;
- case XK_8: return Qt::Key_8;
- case XK_9: return Qt::Key_9;
- case XK_colon: return Qt::Key_Colon;
- case XK_semicolon: return Qt::Key_Semicolon;
- case XK_less: return Qt::Key_Less;
- case XK_equal: return Qt::Key_Equal;
- case XK_greater: return Qt::Key_Greater;
- case XK_question: return Qt::Key_Question;
- case XK_at: return Qt::Key_At;
- case XK_A: return Qt::Key_A;
- case XK_B: return Qt::Key_B;
- case XK_C: return Qt::Key_C;
- case XK_D: return Qt::Key_D;
- case XK_E: return Qt::Key_E;
- case XK_F: return Qt::Key_F;
- case XK_G: return Qt::Key_G;
- case XK_H: return Qt::Key_H;
- case XK_I: return Qt::Key_I;
- case XK_J: return Qt::Key_J;
- case XK_K: return Qt::Key_K;
- case XK_L: return Qt::Key_L;
- case XK_M: return Qt::Key_M;
- case XK_N: return Qt::Key_N;
- case XK_O: return Qt::Key_O;
- case XK_P: return Qt::Key_P;
- case XK_Q: return Qt::Key_Q;
- case XK_R: return Qt::Key_R;
- case XK_S: return Qt::Key_S;
- case XK_T: return Qt::Key_T;
- case XK_U: return Qt::Key_U;
- case XK_V: return Qt::Key_V;
- case XK_W: return Qt::Key_W;
- case XK_X: return Qt::Key_X;
- case XK_Y : return Qt::Key_Y;
- case XK_Z: return Qt::Key_Z;
- case XK_bracketleft: return Qt::Key_BracketLeft;
- case XK_backslash: return Qt::Key_Backslash;
- case XK_bracketright: return Qt::Key_BracketRight;
- case XK_asciicircum: return Qt::Key_AsciiCircum;
- case XK_underscore: return Qt::Key_Underscore;
- case XK_grave: return Qt::Key_Agrave;
- case XK_a: return Qt::Key_A;
- case XK_b: return Qt::Key_B;
- case XK_c: return Qt::Key_C;
- case XK_d: return Qt::Key_D;
- case XK_e: return Qt::Key_E;
- case XK_f : return Qt::Key_F;
- case XK_g: return Qt::Key_G;
- case XK_h: return Qt::Key_H;
- case XK_i: return Qt::Key_I;
- case XK_j: return Qt::Key_J;
- case XK_k: return Qt::Key_K;
- case XK_l: return Qt::Key_L;
- case XK_m: return Qt::Key_M;
- case XK_n: return Qt::Key_N;
- case XK_o: return Qt::Key_O;
- case XK_p: return Qt::Key_P;
- case XK_q: return Qt::Key_Q;
- case XK_r: return Qt::Key_R;
- case XK_s: return Qt::Key_S;
- case XK_t : return Qt::Key_T;
- case XK_u: return Qt::Key_U;
- case XK_v: return Qt::Key_V;
- case XK_w: return Qt::Key_W;
- case XK_x: return Qt::Key_X;
- case XK_y: return Qt::Key_Y;
- case XK_z: return Qt::Key_Z;
- case XK_braceleft: return Qt::Key_BraceLeft;
- case XK_bar: return Qt::Key_Bar;
- case XK_braceright: return Qt::Key_BraceRight;
- case XK_asciitilde: return Qt::Key_AsciiTilde;
-
- case XK_nobreakspace: return Qt::Key_nobreakspace;
- case XK_exclamdown: return Qt::Key_exclamdown;
- case XK_cent: return Qt::Key_cent;
- case XK_sterling: return Qt::Key_sterling;
- case XK_currency: return Qt::Key_currency;
- case XK_yen: return Qt::Key_yen;
- case XK_brokenbar: return Qt::Key_brokenbar;
- case XK_section: return Qt::Key_section;
- case XK_diaeresis: return Qt::Key_diaeresis;
- case XK_copyright: return Qt::Key_copyright;
- case XK_ordfeminine: return Qt::Key_ordfeminine;
- case XK_guillemotleft: return Qt::Key_guillemotleft;
- case XK_notsign: return Qt::Key_notsign;
- case XK_hyphen: return Qt::Key_hyphen;
- case XK_registered: return Qt::Key_registered;
- case XK_macron: return Qt::Key_macron;
- case XK_degree: return Qt::Key_degree;
- case XK_plusminus: return Qt::Key_plusminus;
- case XK_twosuperior: return Qt::Key_twosuperior;
- case XK_threesuperior: return Qt::Key_threesuperior;
- case XK_acute: return Qt::Key_acute;
- case XK_mu: return Qt::Key_mu;
- case XK_paragraph: return Qt::Key_paragraph;
- case XK_periodcentered: return Qt::Key_periodcentered;
- case XK_cedilla: return Qt::Key_cedilla;
- case XK_onesuperior: return Qt::Key_onesuperior;
- case XK_masculine: return Qt::Key_masculine;
- case XK_guillemotright: return Qt::Key_guillemotright;
- case XK_onequarter: return Qt::Key_onequarter;
- case XK_onehalf: return Qt::Key_onehalf;
- case XK_threequarters: return Qt::Key_threequarters;
- case XK_questiondown: return Qt::Key_questiondown;
- case XK_Agrave: return Qt::Key_Agrave;
- case XK_Aacute: return Qt::Key_Aacute;
- case XK_Acircumflex: return Qt::Key_Acircumflex;
- case XK_Atilde: return Qt::Key_Atilde;
- case XK_Adiaeresis: return Qt::Key_Adiaeresis;
- case XK_Aring: return Qt::Key_Aring;
- case XK_AE: return Qt::Key_AE;
- case XK_Ccedilla: return Qt::Key_Ccedilla;
- case XK_Egrave: return Qt::Key_Egrave;
- case XK_Eacute: return Qt::Key_Eacute;
- case XK_Ecircumflex: return Qt::Key_Ecircumflex;
- case XK_Ediaeresis: return Qt::Key_Ediaeresis;
- case XK_Igrave: return Qt::Key_Igrave;
- case XK_Iacute: return Qt::Key_Iacute;
- case XK_Icircumflex: return Qt::Key_Icircumflex;
- case XK_Idiaeresis: return Qt::Key_Idiaeresis;
- case XK_ETH: return Qt::Key_ETH;
- //case XK_Eth: return Qt::Key_Eth;
- case XK_Ntilde: return Qt::Key_Ntilde;
- case XK_Ograve: return Qt::Key_Ograve;
- case XK_Oacute: return Qt::Key_Oacute;
- case XK_Ocircumflex: return Qt::Key_Ocircumflex;
- case XK_Otilde: return Qt::Key_Otilde;
- case XK_Odiaeresis: return Qt::Key_Odiaeresis;
- case XK_multiply: return Qt::Key_multiply;
- //case XK_Oslash: return Qt::Key_AsciiTilde;
- case XK_Ooblique: return Qt::Key_Ooblique;
- case XK_Ugrave: return Qt::Key_Ugrave;
- case XK_Uacute: return Qt::Key_Uacute;
- case XK_Ucircumflex: return Qt::Key_Ucircumflex;
- case XK_Udiaeresis: return Qt::Key_Udiaeresis;
- case XK_Yacute: return Qt::Key_Yacute;
- case XK_THORN: return Qt::Key_THORN;
- //case XK_Thorn: return Qt::Key_AsciiTilde;
- case XK_ssharp: return Qt::Key_ssharp;
- /*case XK_agrave: return Qt::Key_AsciiTilde;
- case XK_aacute: return Qt::Key_AsciiTilde;
- case XK_acircumflex: return Qt::Key_AsciiTilde;
- case XK_atilde: return Qt::Key_AsciiTilde;
- case XK_adiaeresis: return Qt::Key_AsciiTilde;
- case XK_aring: return Qt::Key_AsciiTilde;
- case XK_ae: return Qt::Key_AsciiTilde;
- case XK_ccedilla: return Qt::Key_AsciiTilde;
- case XK_egrave: return Qt::Key_AsciiTilde;
- case XK_eacute: return Qt::Key_AsciiTilde;
- case XK_ecircumflex: return Qt::Key_AsciiTilde;
- case XK_ediaeresis: return Qt::Key_AsciiTilde;
- case XK_igrave: return Qt::Key_AsciiTilde;
- case XK_iacute: return Qt::Key_AsciiTilde;
- case XK_icircumflex: return Qt::Key_AsciiTilde;
- case XK_idiaeresis: return Qt::Key_AsciiTilde;
- case XK_eth: return Qt::Key_AsciiTilde;
- case XK_ntilde: return Qt::Key_AsciiTilde;
- case XK_ograve: return Qt::Key_AsciiTilde;
- case XK_oacute: return Qt::Key_AsciiTilde;
- case XK_ocircumflex: return Qt::Key_AsciiTilde;
- case XK_otilde: return Qt::Key_AsciiTilde;
- case XK_odiaeresis: return Qt::Key_AsciiTilde;
- case XK_division: return Qt::Key_AsciiTilde;
- case XK_oslash: return Qt::Key_AsciiTilde;
- case XK_ooblique: return Qt::Key_AsciiTilde;
- case XK_ugrave: return Qt::Key_AsciiTilde;
- case XK_uacute: return Qt::Key_AsciiTilde;
- case XK_ucircumflex: return Qt::Key_AsciiTilde;
- case XK_udiaeresis: return Qt::Key_AsciiTilde;
- case XK_yacute: return Qt::Key_AsciiTilde;
- case XK_thorn: return Qt::Key_AsciiTilde;
- case XK_ydiaeresis: return Qt::Key_AsciiTilde;
-
- case: XK_Agonek: return Qt::Key_AsciiTilde;
- case XK_breve: return Qt::Key_AsciiTilde;
- case XK_Lstroke: return Qt::Key_AsciiTilde;
- case XK_Lcaron: return Qt::Key_AsciiTilde;
- case XK_Sacute: return Qt::Key_AsciiTilde;
- case XK_Scaron: return Qt::Key_AsciiTilde;
- case XK_Scedilla: return Qt::Key_AsciiTilde;
- case XK_Tcaron: return Qt::Key_AsciiTilde;
- case XK_Zacute: return Qt::Key_AsciiTilde;
- case XK_Zcaron: return Qt::Key_AsciiTilde;
- case XK_Zabovedot: return Qt::Key_AsciiTilde;
- case XK_aogonek: return Qt::Key_AsciiTilde;
- case XK_ogonek: return Qt::Key_AsciiTilde;
- case XK_lstroke: return Qt::Key_AsciiTilde;
- case XK_lcaron: return Qt::Key_AsciiTilde;
- case XK_sacute: return Qt::Key_AsciiTilde;
- case XK_caron: return Qt::Key_AsciiTilde;
- case XK_scaron: return Qt::Key_AsciiTilde;
- case XK_scedilla: return Qt::Key_AsciiTilde;
- case XK_tcaron: return Qt::Key_AsciiTilde;
- case XK_zacute: return Qt::Key_AsciiTilde;
- case XK_doubleacute: return Qt::Key_AsciiTilde;
- case XK_zcaron: return Qt::Key_AsciiTilde;
- case XK_zabovedot: return Qt::Key_AsciiTilde;
- case XK_Racute: return Qt::Key_AsciiTilde;
- case XK_Abreve: return Qt::Key_AsciiTilde;
- case XK_Lacute: return Qt::Key_AsciiTilde;
- case XK_Cacute: return Qt::Key_AsciiTilde;
- case XK_Ccaron: return Qt::Key_AsciiTilde;
- case XK_Eogonek: return Qt::Key_AsciiTilde;
- case XK_Ecaron: return Qt::Key_AsciiTilde;
- case XK_Dcaron: return Qt::Key_AsciiTilde;
- case XK_Dstroke: return Qt::Key_AsciiTilde;
- case XK_Nacute: return Qt::Key_AsciiTilde;
- case XK_Ncaron: return Qt::Key_AsciiTilde;
- case XK_Odoubleacute: return Qt::Key_AsciiTilde;
- case XK_Rcaron: return Qt::Key_AsciiTilde;
- case XK_Uring: return Qt::Key_AsciiTilde;
- case XK_Udoubleacute: return Qt::Key_AsciiTilde;
- case XK_Tcedilla: return Qt::Key_AsciiTilde;
- case XK_racute: return Qt::Key_AsciiTilde;
- case XK_abreve: return Qt::Key_AsciiTilde;
- case XK_lacute: return Qt::Key_AsciiTilde;
- case XK_cacute: return Qt::Key_AsciiTilde;
- case XK_ccaron: return Qt::Key_AsciiTilde;
- case XK_eogonek: return Qt::Key_AsciiTilde;
- case XK_ecaron: return Qt::Key_AsciiTilde;
- case XK_dcaron: return Qt::Key_AsciiTilde;
- case XK_dstroke: return Qt::Key_AsciiTilde;
- case XK_nacute: return Qt::Key_AsciiTilde;
- case XK_ncaron: return Qt::Key_AsciiTilde;
- case XK_odoubleacute: return Qt::Key_AsciiTilde;
- case XK_rcaron: return Qt::Key_AsciiTilde;
- case XK_uring: return Qt::Key_AsciiTilde;
- case XK_udoubleacute: return Qt::Key_AsciiTilde;
- case XK_tcedilla: return Qt::Key_AsciiTilde;
- case XK_abovedot: return Qt::Key_AsciiTilde;
- case XK_Hstroke: return Qt::Key_AsciiTilde;
- case XK_Hcircumflex: return Qt::Key_AsciiTilde;
- case XK_Iabovedot: return Qt::Key_AsciiTilde;
- case XK_Gbreve: return Qt::Key_AsciiTilde;
- case XK_Jcircumflex: return Qt::Key_AsciiTilde;
- case XK_hstroke: return Qt::Key_AsciiTilde;
- case XK_hcircumflex: return Qt::Key_AsciiTilde;
- case XK_idotless: return Qt::Key_AsciiTilde;
- case XK_gbreve: return Qt::Key_AsciiTilde;
- case XK_jcircumflex: return Qt::Key_AsciiTilde;
- case XK_Cabovedot: return Qt::Key_AsciiTilde;
- case XK_Ccircumflex: return Qt::Key_AsciiTilde;
- case XK_Gabovedot: return Qt::Key_AsciiTilde;
- case XK_Gcircumflex: return Qt::Key_AsciiTilde;
- case XK_Ubreve: return Qt::Key_AsciiTilde;
- case XK_Scircumflex: return Qt::Key_AsciiTilde;
- case XK_cabovedot: return Qt::Key_AsciiTilde;
- case XK_ccircumflex: return Qt::Key_AsciiTilde;
- case XK_gabovedot: return Qt::Key_AsciiTilde;
- case XK_gcircumflex: return Qt::Key_AsciiTilde;
- case XK_ubreve: return Qt::Key_AsciiTilde;
- case XK_scircumflex: return Qt::Key_AsciiTilde;
- case XK_kra: return Qt::Key_AsciiTilde;
- case XK_kappa: return Qt::Key_AsciiTilde;
- case XK_Rcedilla: return Qt::Key_AsciiTilde;
- case XK_Itilde: return Qt::Key_AsciiTilde;
- case XK_Lcedilla: return Qt::Key_AsciiTilde;
- case XK_Emacron: return Qt::Key_AsciiTilde;
- case XK_Gcedilla: return Qt::Key_AsciiTilde;
- case XK_Tslash: return Qt::Key_AsciiTilde;
- case XK_rcedilla: return Qt::Key_AsciiTilde;
- case XK_itilde: return Qt::Key_AsciiTilde;
- case XK_lcedilla: return Qt::Key_AsciiTilde;
- case XK_emacron: return Qt::Key_AsciiTilde;
- case XK_gcedilla: return Qt::Key_AsciiTilde;
- case XK_tslash: return Qt::Key_AsciiTilde;
- case XK_ENG: return Qt::Key_AsciiTilde;
- case XK_eng: return Qt::Key_AsciiTilde;
- case XK_Amacron: return Qt::Key_AsciiTilde;
- case XK_Iogonek: return Qt::Key_AsciiTilde;
- case XK_Eabovedot: return Qt::Key_AsciiTilde;
- case XK_Imacron: return Qt::Key_AsciiTilde;
- case XK_Ncedilla: return Qt::Key_AsciiTilde;
- case XK_Omacron: return Qt::Key_AsciiTilde;
- case XK_Kcedilla: return Qt::Key_AsciiTilde;
- case XK_Uogonek: return Qt::Key_AsciiTilde;
- case XK_Utilde: return Qt::Key_AsciiTilde;
- case XK_Umacron: return Qt::Key_AsciiTilde;
- case XK_amacron: return Qt::Key_AsciiTilde;
- case XK_iogonek: return Qt::Key_AsciiTilde;
- case XK_eabovedot: return Qt::Key_AsciiTilde;
- case XK_imacron: return Qt::Key_AsciiTilde;
- case XK_ncedilla: return Qt::Key_AsciiTilde;
- case XK_omacron: return Qt::Key_AsciiTilde;
- case XK_kcedilla: return Qt::Key_AsciiTilde;
- case XK_uogonek: return Qt::Key_AsciiTilde;
- case XK_utilde: return Qt::Key_AsciiTilde;
- case XK_umacron: return Qt::Key_AsciiTilde;
- case XK_Wcircumflex: return Qt::Key_AsciiTilde;
- case XK_wcircumflex: return Qt::Key_AsciiTilde;
- case XK_Ycircumflex: return Qt::Key_AsciiTilde;
- case XK_ycircumflex: return Qt::Key_AsciiTilde;
- case XK_Babovedot: return Qt::Key_AsciiTilde;
- case XK_babovedot: return Qt::Key_AsciiTilde;
- case XK_Dabovedot: return Qt::Key_AsciiTilde;
- case XK_dabovedot: return Qt::Key_AsciiTilde;
- case XK_Fabovedot: return Qt::Key_AsciiTilde;
- case XK_fabovedot: return Qt::Key_AsciiTilde;
- case XK_Mabovedot: return Qt::Key_AsciiTilde;
- case XK_mabovedot: return Qt::Key_AsciiTilde;
- case XK_Pabovedot: return Qt::Key_AsciiTilde;
- case XK_pabovedot: return Qt::Key_AsciiTilde;
- case XK_Sabovedot: return Qt::Key_AsciiTilde;
- case XK_sabovedot: return Qt::Key_AsciiTilde;
- case XK_Tabovedot: return Qt::Key_AsciiTilde;
- case XK_tabovedot: return Qt::Key_AsciiTilde;
- case XK_Wgrave: return Qt::Key_AsciiTilde;
- case XK_wgrave: return Qt::Key_AsciiTilde;
- case XK_Wacute: return Qt::Key_AsciiTilde;
- case XK_wacute: return Qt::Key_AsciiTilde;
- case XK_Wdiaeresis: return Qt::Key_AsciiTilde;
- case XK_wdiaeresis: return Qt::Key_AsciiTilde;
- case XK_Ygrave: return Qt::Key_AsciiTilde;
- case XK_ygrave: return Qt::Key_AsciiTilde;
- case XK_OE: return Qt::Key_AsciiTilde;
- case XK_oe: return Qt::Key_AsciiTilde;
- case XK_Ydiaeresis: return Qt::Key_AsciiTilde;*/
- default:
- qDebug() << "Unknown Key";
- }
- qDebug() << " -- Simple Qt Map:" << (Qt::Key)(symbol);
- qDebug() << " -- Key Sequence Map:" << QKeySequence(symbol);
- qDebug() << " - Not implemented yet";
- return Qt::Key_unknown;
-}
-
-NativeWindowSystem::MouseButton NativeWindowSystem::MouseToQt(int keycode){
- switch(keycode){
- case 1:
- return NativeWindowSystem::LeftButton;
- case 3:
- return NativeWindowSystem::RightButton;
- case 2:
- return NativeWindowSystem::MidButton;
- case 4:
- return NativeWindowSystem::WheelUp;
- case 5:
- return NativeWindowSystem::WheelDown;
- case 6:
- return NativeWindowSystem::WheelLeft;
- case 7:
- return NativeWindowSystem::WheelRight;
- case 8:
- return NativeWindowSystem::BackButton; //Not sure if this is correct yet (1/27/17)
- case 9:
- return NativeWindowSystem::ForwardButton; //Not sure if this is correct yet (1/27/17)
- default:
- return NativeWindowSystem::NoButton;
- }
-}
diff --git a/src-qt5/src-cpp/NativeWindowSystem.cpp b/src-qt5/src-cpp/NativeWindowSystem.cpp
deleted file mode 100644
index e8e9655a..00000000
--- a/src-qt5/src-cpp/NativeWindowSystem.cpp
+++ /dev/null
@@ -1,986 +0,0 @@
-//===========================================
-// 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>
-#include <QApplication>
-#include <QScreen>
-#include <QFont>
-#include <QFontMetrics>
-#include <QKeySequence>
-
-
-//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_NOTIFY | \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_PROPERTY_CHANGE | \
- XCB_EVENT_MASK_FOCUS_CHANGE | \
- XCB_EVENT_MASK_ENTER_WINDOW)
-
-#define NORMAL_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \
- XCB_EVENT_MASK_BUTTON_RELEASE | \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_BUTTON_MOTION | \
- XCB_EVENT_MASK_EXPOSURE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_ENTER_WINDOW | \
- XCB_EVENT_MASK_PROPERTY_CHANGE | \
- XCB_EVENT_MASK_FOCUS_CHANGE)
-
-#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_FOCUS_CHANGE | \
- XCB_EVENT_MASK_POINTER_MOTION)
-
-#define FRAME_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \
- XCB_EVENT_MASK_BUTTON_RELEASE | \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_EXPOSURE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_ENTER_WINDOW)
-
-inline void registerClientEvents(WId id, bool client = true){
- uint32_t values[] = {XCB_NONE};
- values[0] = client ? CLIENT_EVENT_MASK : FRAME_EVENT_MASK ;
- /*{ (XCB_EVENT_MASK_PROPERTY_CHANGE
- | XCB_EVENT_MASK_BUTTON_PRESS
- | XCB_EVENT_MASK_BUTTON_RELEASE
- | XCB_EVENT_MASK_POINTER_MOTION
- | XCB_EVENT_MASK_BUTTON_MOTION
- | XCB_EVENT_MASK_EXPOSURE
- | XCB_EVENT_MASK_STRUCTURE_NOTIFY
- | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
- | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
- | XCB_EVENT_MASK_ENTER_WINDOW)
- };*/
- xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, values);
-}
-
-/*inline void registerClientEvents(WId id){
- uint32_t value_list[1] = {NORMAL_WIN_EVENT_MASK};
- xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list);
-}*/
-
-//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(){
- xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH);
- if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){
- qDebug() << "Error with XCB atom initializations";
- return false;
- }
-
- QStringList atoms;
- atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW" << "WM_PROTOCOLS" << "_NET_WM_WINDOW_OPACITY"
- << "WM_CHANGE_STATE" << "_NET_SYSTEM_TRAY_OPCODE" << "_NET_SYSTEM_TRAY_ORIENTATION" << "_XEMBED"
- << "_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){
- 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 (ATOMS.keys().length() == atoms.length());
- }
-
- WId getTransientFor(WId win){
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for_unchecked(QX11Info::connection(), win);
- xcb_window_t trans;
- if(1!= xcb_icccm_get_wm_transient_for_reply(QX11Info::connection(), cookie, &trans, NULL) ){
- return win; //error in fetching transient window ID (or none found)
- }else{
- return trans;
- }
-}
-
- 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, \
- wm_window, 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 start_system_tray(){
- 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)
- tray_window = xcb_generate_id(QX11Info::connection()); //need a new ID
- uint32_t params[] = {1};
- xcb_create_window(QX11Info::connection(), root_screen->root_depth, \
- tray_window, root_screen->root, -1, -1, 1, 1, 0, \
- XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \
- XCB_CW_OVERRIDE_REDIRECT, params);
- //Now register this widget as the system tray
- xcb_set_selection_owner(QX11Info::connection(), tray_window, _NET_SYSTEM_TRAY_S, XCB_CURRENT_TIME);
- //Make sure that it was registered properly
- ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \
- xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL);
- if(ownreply==0 || ownreply->owner != tray_window){
- if(ownreply!=0){ free(ownreply); }
- qWarning() << " - Could not register the system tray";
- xcb_destroy_window(QX11Info::connection(), tray_window);
- return false;
- }
- free(ownreply); //done with structure
- //Now register the orientation of the system tray
- uint32_t orient = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
- xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, tray_window, \
- ATOMS.value("_NET_SYSTEM_TRAY_ORIENTATION"), XCB_ATOM_CARDINAL, 32, 1, &orient);
-
- //Now set the visual ID for the system tray (same as the root window, but TrueColor)
- xcb_visualtype_t *type = xcb_aux_find_visual_by_attrs(root_screen, XCB_VISUAL_CLASS_TRUE_COLOR, 32);
- if(type!=0){
- xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, tray_window, \
- ATOMS.value("_NET_SYSTEM_TRAY_VISUAL"), XCB_ATOM_VISUALID, 32, 1, &type->visual_id);
- }else{
- qWarning() << " - Could not set TrueColor visual for system tray";
- }
-
- //Finally, send out an X event letting others know that the system tray is up and running
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = root_screen->root;
- event.type = EWMH.MANAGER; //MANAGER atom
- event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime;
- event.data.data32[1] = _NET_SYSTEM_TRAY_S; //_NET_SYSTEM_TRAY_S atom
- event.data.data32[2] = tray_window;
- event.data.data32[3] = 0;
- event.data.data32[4] = 0;
-
- xcb_send_event(QX11Info::connection(), 0, root_screen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
- return true;
- }
-
-}; //end private objects class
-
-
-//inline functions for setting up the internal objects
-
-
-// === PUBLIC ===
-NativeWindowSystem::NativeWindowSystem() : QObject(){
- obj = 0;
- pingTimer = 0;
- screenLocked = false;
-}
-
-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
- bool ok = obj->register_wm();
- if(ok){
- setRoot_supportedActions();
- ok = obj->start_system_tray();
- }else{
- qWarning() << "Could not register the WM";
- }
- return ok;
-}
-
-void NativeWindowSystem::stop(){
-
-}
-
-// === PRIVATE ===
-NativeWindow* NativeWindowSystem::findWindow(WId id, bool checkRelated){
- //qDebug() << "Find Window:" << id;
- for(int i=0; i<NWindows.length(); i++){
- if(id==NWindows[i]->id() ){ return NWindows[i]; }
- else if(id==NWindows[i]->frameId() ){ return NWindows[i]; }
- //if(checkRelated && NWindows[i]->isRelatedTo(id)){ return NWindows[i]; }
- //else if(!checkRelated && id==NWindows[i]->id()){ return NWindows[i]; }
- }
- //Check to see if this is a transient for some other window
- if(checkRelated){
- //WId tid = obj->getTransientFor(id);
- //if(tid!=id){ return findWindow(tid, checkRelated); } //call it recursively as needed
- //qDebug() << " -- Could not find Window!";
- }
- return 0;
-}
-
-NativeWindow* NativeWindowSystem::findTrayWindow(WId id){
- for(int i=0; i<TWindows.length(); i++){
- if(TWindows[i]->isRelatedTo(id)){ return TWindows[i]; }
- }
- return 0;
-}
-
-void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props){
- //Put the properties in logical groups as appropriate (some XCB calls return multiple properties)
- if(props.contains(NativeWindow::Title)){
- //Try the EWMH standards first
- // _NET_WM_NAME
- QString name;
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name_unchecked(&obj->EWMH, win->id());
- if(cookie.sequence != 0){
- xcb_ewmh_get_utf8_strings_reply_t data;
- if( 1 == xcb_ewmh_get_wm_name_reply(&obj->EWMH, cookie, &data, NULL) ){
- name = QString::fromUtf8(data.strings, data.strings_len);
- }
- }
- if(name.isEmpty()){
- //_NET_WM_VISIBLE_NAME
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_name_unchecked(&obj->EWMH, win->id());
- if(cookie.sequence != 0){
- xcb_ewmh_get_utf8_strings_reply_t data;
- if( 1 == xcb_ewmh_get_wm_visible_name_reply(&obj->EWMH, cookie, &data, NULL) ){
- name = QString::fromUtf8(data.strings, data.strings_len);
- }
- }
- }
- if(name.isEmpty()){
- //Now try the ICCCM standard
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_name_unchecked(QX11Info::connection(), win->id());
- xcb_icccm_get_text_property_reply_t reply;
- if(1 == xcb_icccm_get_wm_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){
- name = QString::fromLocal8Bit(reply.name, reply.name_len);
- xcb_icccm_get_text_property_reply_wipe(&reply);
- }
- }
- win->setProperty(NativeWindow::Title, name);
- } //end TITLE property
-
- if(props.contains(NativeWindow::ShortTitle)){
- //Try the EWMH standards first
- // _NET_WM_ICON_NAME
- QString name;
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name_unchecked(&obj->EWMH, win->id());
- if(cookie.sequence != 0){
- xcb_ewmh_get_utf8_strings_reply_t data;
- if( 1 == xcb_ewmh_get_wm_icon_name_reply(&obj->EWMH, cookie, &data, NULL) ){
- name = QString::fromUtf8(data.strings, data.strings_len);
- }
- }
- if(name.isEmpty()){
- //_NET_WM_VISIBLE_ICON_NAME
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_icon_name_unchecked(&obj->EWMH, win->id());
- if(cookie.sequence != 0){
- xcb_ewmh_get_utf8_strings_reply_t data;
- if( 1 == xcb_ewmh_get_wm_visible_icon_name_reply(&obj->EWMH, cookie, &data, NULL) ){
- name = QString::fromUtf8(data.strings, data.strings_len);
- }
- }
- }
- if(name.isEmpty()){
- //Now try the ICCCM standard
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_icon_name_unchecked(QX11Info::connection(), win->id());
- xcb_icccm_get_text_property_reply_t reply;
- if(1 == xcb_icccm_get_wm_icon_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){
- name = QString::fromLocal8Bit(reply.name, reply.name_len);
- xcb_icccm_get_text_property_reply_wipe(&reply);
- }
- }
- win->setProperty(NativeWindow::ShortTitle, name);
- } //end SHORTTITLE property
-
- if(props.contains(NativeWindow::Icon)){
- //See if this is a tray icon first (different routine - entire app window is the icon)
- QIcon icon;
- if(win == findTrayWindow(win->id())){
- //Tray Icon Window
- QPixmap pix;
- //Get the current QScreen (for XCB->Qt conversion)
- QList<QScreen*> scrnlist = QApplication::screens();
- //Try to grab the given window directly with Qt
- for(int i=0; i<scrnlist.length() && pix.isNull(); i++){
- pix = scrnlist[i]->grabWindow(win->id());
- }
- icon.addPixmap(pix);
- }else{
- //Standard window
- //Fetch the _NET_WM_ICON for the window and return it as a QIcon
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_unchecked(&obj->EWMH, win->id());
- xcb_ewmh_get_wm_icon_reply_t reply;
- if(1 == xcb_ewmh_get_wm_icon_reply(&obj->EWMH, cookie, &reply, NULL)){
- xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&reply);
- //Just use the first
- bool done =false;
- while(!done){
- //Now convert the current data into a Qt image
- // - first 2 elements are width and height (removed via XCB functions)
- // - data in rows from left to right and top to bottom
- QImage image(iter.width, iter.height, QImage::Format_ARGB32); //initial setup
- uint* dat = iter.data;
- //dat+=2; //remember the first 2 element offset
- for(int i=0; i<image.byteCount()/4; ++i, ++dat){
- ((uint*)image.bits())[i] = *dat;
- }
- icon.addPixmap(QPixmap::fromImage(image)); //layer this pixmap onto the icon
- //Now see if there are any more icons available
- done = (iter.rem<1); //number of icons remaining
- if(!done){ xcb_ewmh_get_wm_icon_next(&iter); } //get the next icon data
- }
- xcb_ewmh_get_wm_icon_reply_wipe(&reply);
- }
- } //end type of window
- win->setProperty(NativeWindow::Icon, icon);
- } //end ICON property
-
- if(props.contains(NativeWindow::MinSize) || props.contains(NativeWindow::MaxSize)
- || props.contains(NativeWindow::Size) || props.contains(NativeWindow::GlobalPos) ){
- //Try the ICCCM "Normal Hints" structure first (newer spec?)
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_normal_hints_unchecked(QX11Info::connection(), win->id());
- xcb_size_hints_t reply;
- bool ok = false;
- if(1==xcb_icccm_get_wm_normal_hints_reply(QX11Info::connection(), cookie, &reply, NULL) ){ ok = true; }
- else{
- //Could not find normal hints, try the older "size hints" instead
- cookie = xcb_icccm_get_wm_size_hints_unchecked(QX11Info::connection(), win->id(), XCB_ATOM_WM_SIZE_HINTS);
- if(1==xcb_icccm_get_wm_size_hints_reply(QX11Info::connection(), cookie, &reply, NULL) ){ ok = true; }
- }
- if(ok){
- bool initsize = win->property(NativeWindow::Size).isNull(); //initial window size
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_US_POSITION)==XCB_ICCCM_SIZE_HINT_US_POSITION ){ win->setProperty(NativeWindow::GlobalPos, QPoint(reply.x,reply.y)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_US_SIZE)==XCB_ICCCM_SIZE_HINT_US_SIZE ){ win->setProperty(NativeWindow::Size, QSize(reply.width, reply.height)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_POSITION)==XCB_ICCCM_SIZE_HINT_P_POSITION ){ win->setProperty(NativeWindow::GlobalPos, QPoint(reply.x,reply.y)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_SIZE)==XCB_ICCCM_SIZE_HINT_P_SIZE ){ win->setProperty(NativeWindow::Size, QSize(reply.width, reply.height)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)==XCB_ICCCM_SIZE_HINT_P_MIN_SIZE ){ win->setProperty(NativeWindow::MinSize, QSize(reply.min_width, reply.min_height)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)==XCB_ICCCM_SIZE_HINT_P_MAX_SIZE ){ win->setProperty(NativeWindow::MaxSize, QSize(reply.max_width, reply.max_height)); }
- if( (reply.flags&XCB_ICCCM_SIZE_HINT_BASE_SIZE)==XCB_ICCCM_SIZE_HINT_BASE_SIZE && initsize ){ win->setProperty(NativeWindow::Size, QSize(reply.base_width, reply.base_height)); }
- //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)==XCB_ICCCM_SIZE_HINT_P_RESIZE_INC ){ hints.width_inc=reply.width_inc; hints.height_inc=reply.height_inc; }
- //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_ASPECT)==XCB_ICCCM_SIZE_HINT_P_ASPECT ){ hints.min_aspect_num=reply.min_aspect_num; hints.min_aspect_den=reply.min_aspect_den; hints.max_aspect_num=reply.max_aspect_num; hints.max_aspect_den=reply.max_aspect_den;}
- //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)==XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY ){ hints.win_gravity=reply.win_gravity; }
- }
- } //end of geometry properties
-
- if(props.contains(NativeWindow::Name)){
- //Put the app/class name here (much more static than the "Title" properties
- xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class_unchecked(QX11Info::connection(), win->id());
- xcb_icccm_get_wm_class_reply_t reply;
- if(1 == xcb_icccm_get_wm_class_reply(QX11Info::connection(), cookie, &reply, NULL) ){
- //Returns: "<instance name>::::<class name>"
- win->setProperty(NativeWindow::Name, ( QString::fromLocal8Bit(reply.instance_name)+"::::"+QString::fromLocal8Bit(reply.class_name) ));
- xcb_icccm_get_wm_class_reply_wipe(&reply);
- }
- } //end NAME property
-
- if(props.contains(NativeWindow::Workspace)){
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop_unchecked(&obj->EWMH, win->id());
- uint32_t num = 0;
- int wkspace = -1;
- if(1==xcb_ewmh_get_wm_desktop_reply(&obj->EWMH, cookie, &num, NULL) ){
- if(num!=0xFFFFFFFF){ wkspace = num; }
- }/*else{
- //Error in fetching property (not set?)
- // - put it on the current screen
- out = WM_Get_Current_Desktop();
- }*/
- win->setProperty(NativeWindow::Workspace, wkspace);
- }
- if(props.contains(NativeWindow::FrameExtents)){
- //Just assign default values to this - need to automate it later
- //win->setProperty(NativeWindow::FrameExtents, QVariant::fromValue<QList<int> >(QList<int>() << 5 << 5 << 5+QFontMetrics(QFont()).height() << 5) );
- }
- if(props.contains(NativeWindow::RelatedWindows)){
- WId orig = win->id();
- WId tid = obj->getTransientFor(orig);
- QList<WId> list;
- while(tid != orig){
- list << tid;
- orig = tid;
- tid = obj->getTransientFor(orig);
- }
- win->setProperty(NativeWindow::RelatedWindows, QVariant::fromValue(list));
- }
- if(props.contains(NativeWindow::Visible)){
- xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), xcb_get_window_attributes(QX11Info::connection(), win->id()) , NULL);
- if(attr != 0){
- win->setProperty(NativeWindow::Visible, attr->map_state == XCB_MAP_STATE_VIEWABLE);
- free(attr);
- }
- }
- if(props.contains(NativeWindow::WinTypes)){
- QList< NativeWindow::Type> types;
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type_unchecked(&obj->EWMH, win->id());
- xcb_ewmh_get_atoms_reply_t reply;
- if(1==xcb_ewmh_get_wm_window_type_reply(&obj->EWMH, cookie, &reply, NULL) ){
- for(unsigned int i=0; i<reply.atoms_len; i++){
- if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DESKTOP){ types << NativeWindow::T_DESKTOP; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DOCK){ types << NativeWindow::T_DOCK; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_TOOLBAR){ types << NativeWindow::T_TOOLBAR; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_MENU){ types << NativeWindow::T_MENU; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_UTILITY){ types << NativeWindow::T_UTILITY; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_SPLASH){ types << NativeWindow::T_SPLASH; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DIALOG){ types << NativeWindow::T_DIALOG; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU){ types << NativeWindow::T_DROPDOWN_MENU; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU){ types << NativeWindow::T_POPUP_MENU; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_TOOLTIP){ types << NativeWindow::T_TOOLTIP; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION){ types << NativeWindow::T_NOTIFICATION; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_COMBO){ types << NativeWindow::T_COMBO; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DND){ types << NativeWindow::T_DND; }
- else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_NORMAL){ types << NativeWindow::T_NORMAL; }
- }
- }
- if(types.isEmpty()){ types << NativeWindow::T_NORMAL; }
- win->setProperty(NativeWindow::WinTypes, QVariant::fromValue< QList<NativeWindow::Type> >(types) );
- }
-}
-
-void NativeWindowSystem::ChangeWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props, QList<QVariant> vals){
- if(props.length() == 0 || vals.length()!=props.length() || win ==0 ){ return; }
- //qDebug() << "Change Window Properties:" << props << vals;
- if(props.contains(NativeWindow::Title)){
-
- }
- if(props.contains(NativeWindow::ShortTitle)){
-
- }
- if(props.contains(NativeWindow::Icon)){
-
- }
- if(props.contains(NativeWindow::Size) || props.contains(NativeWindow::GlobalPos) ){
- /*xcb_configure_window_value_list_t valList;
- //valList.x = 0; //Note that this is the relative position - should always be 0,0 relative to the embed widget
- //valList.y = 0;
- QSize sz = win->property(NativeWindow::Size).toSize();
- if(props.contains(NativeWindow::Size)){
- sz = vals[ props.indexOf(NativeWindow::Size) ] .toSize();
- }
- valList.width = sz.width();
- valList.height = sz.height();
- if(props.contains(NativeWindow::GlobalPos)){
- QPoint pt = vals[ props.indexOf(NativeWindow::GlobalPos) ] .toPoint();
- valList.x = pt.x();
- valList.y = pt.y();
- }else{
- valList.x = win->property(NativeWindow::GlobalPos).toPoint().x();
- valList.y = win->property(NativeWindow::GlobalPos).toPoint().y();
- }
- uint16_t mask = 0;
- mask = mask | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
- //qDebug() << "Configure window Geometry:" << sz;
- xcb_configure_window_aux(QX11Info::connection(), win->id(), mask, &valList);*/
- }
- if(props.contains(NativeWindow::Name)){
-
- }
- if(props.contains(NativeWindow::Workspace)){
- int num = vals[ props.indexOf(NativeWindow::Workspace) ].toInt();
- xcb_ewmh_set_wm_desktop(&obj->EWMH, win->id(), (num<0 ? 0xFFFFFFFF : qAbs(num) ) );
- }
- if(props.contains(NativeWindow::RelatedWindows)){
-
- }
- if(props.contains(NativeWindow::Visible)){
- //qDebug() << "Check Window Visibility:" << vals[ props.indexOf(NativeWindow::Visible) ];
- if( vals[ props.indexOf(NativeWindow::Visible) ].toBool() ){
- //qDebug() << " - Map it!";
- xcb_map_window(QX11Info::connection(), win->id());
- }else{
- //qDebug() << " - Unmap it!";
- xcb_unmap_window(QX11Info::connection(), win->id());
- }
- }
- if(props.contains(NativeWindow::Active)){
- //Only one window can be "Active" at a time - so only do anything if this window wants to be active
- if(vals[props.indexOf(NativeWindow::Active)].toBool() ){
- //Lower the currently active window (invisible window) to the bottom of the stack
- xcb_window_t cactive;
- if( 1 == xcb_ewmh_get_active_window_reply( &obj->EWMH,
- xcb_ewmh_get_active_window_unchecked(&obj->EWMH, QX11Info::appScreen()),
- &cactive, NULL) ){
- uint32_t val = XCB_STACK_MODE_BELOW;
- xcb_configure_window(QX11Info::connection(), cactive, XCB_CONFIG_WINDOW_STACK_MODE, &val);
- }
-
- xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), win->id() );
- //Also send the active window a message to take input focus
- xcb_set_input_focus(QX11Info::connection(), XCB_INPUT_FOCUS_PARENT, win->id(), XCB_CURRENT_TIME);
- //Send the window a WM_TAKE_FOCUS message
-/* xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = win->id();
- event.type = obj->ATOMS["WM_PROTOCOLS"];
- event.data.data32[0] = obj->ATOMS["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->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
- xcb_flush(QX11Info::connection());
-*/
- }
- }
-
-}
-
-// === PUBLIC SLOTS ===
-//These are the slots which are typically only used by the desktop system itself or the NativeEventFilter
-void NativeWindowSystem::RegisterVirtualRoot(WId id){
- //Convert to XCB array
- xcb_window_t array[1];
- array[0] = id;
- //Set the property
- xcb_ewmh_set_virtual_roots(&obj->EWMH, QX11Info::appScreen(), 1, array);
- //Now also enable automatic compositing for children of this window
- //xcb_composite_redirect_window(QX11Info::connection(), id, XCB_COMPOSITE_REDIRECT_AUTOMATIC);
- //xcb_composite_redirect_subwindows(QX11Info::connection(), id, XCB_COMPOSITE_REDIRECT_AUTOMATIC);
-}
-
-void NativeWindowSystem::setRoot_supportedActions(){
-//NET_WM standards (ICCCM implied - no standard way to list those)
- xcb_atom_t list[] = {obj->EWMH._NET_WM_NAME,
- obj->EWMH._NET_WM_ICON,
- obj->EWMH._NET_WM_ICON_NAME,
- obj->EWMH._NET_WM_DESKTOP,
- /*obj->ATOMS["_NET_WM_WINDOW_OPACITY"],*/
- /*_NET_WINDOW_TYPE (and all the various types - 15 in total*/
- obj->EWMH._NET_WM_WINDOW_TYPE, obj->EWMH._NET_WM_WINDOW_TYPE_DESKTOP, obj->EWMH._NET_WM_WINDOW_TYPE_DOCK,
- obj->EWMH._NET_WM_WINDOW_TYPE_TOOLBAR, obj->EWMH._NET_WM_WINDOW_TYPE_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_UTILITY,
- obj->EWMH._NET_WM_WINDOW_TYPE_SPLASH, obj->EWMH._NET_WM_WINDOW_TYPE_DIALOG, obj->EWMH._NET_WM_WINDOW_TYPE_NORMAL,
- obj->EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_TOOLTIP,
- obj->EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION, obj->EWMH._NET_WM_WINDOW_TYPE_COMBO, obj->EWMH._NET_WM_WINDOW_TYPE_DND,
- };
- xcb_ewmh_set_supported(&obj->EWMH, QX11Info::appScreen(), 20,list);
-}
-
-void NativeWindowSystem::setRoot_numberOfWorkspaces(QStringList names){
- if(names.isEmpty()){ names << "one"; }
- //First set the overall number of workspaces
- xcb_ewmh_set_number_of_desktops(&obj->EWMH, QX11Info::appScreen(), names.length());
- //Now set the names for the workspaces
- //EWMH LIBRARY BROKEN - appears to be a mismatch in the function header (looking for a single char array, instead of a list of char arrays)
- // Ken Moore - 6/27/17
- /*
- char *array[ names.length() ];
- for(int i=0; i<names.length(); i++){array[i] = names[i].toUtf8().data(); } //Convert to an array of char arrays
- xcb_ewmh_set_desktop_names(&obj->EWMH, QX11Info::appScreen(), names.length(), array);
- */
-}
-
-void NativeWindowSystem::setRoot_currentWorkspace(int num){
- xcb_ewmh_set_current_desktop(&obj->EWMH, QX11Info::appScreen(), num);
-}
-
-void NativeWindowSystem::setRoot_clientList(QList<WId> list, bool stackorder){
- //convert the QList into a generic array
- xcb_window_t array[list.length()];
- for(int i=0; i<list.length(); i++){ array[i] = list[i]; }
- if(stackorder){
- xcb_ewmh_set_client_list_stacking(&obj->EWMH, QX11Info::appScreen(), list.length(), array);
- }else{
- xcb_ewmh_set_client_list(&obj->EWMH, QX11Info::appScreen(), list.length(), array);
- }
-}
-
-void NativeWindowSystem::setRoot_desktopGeometry(QRect geom){
- //This one is a combo function
- // This will set the "DESKTOP_VIEWPORT" property (point)
- // as well as the "DESKTOP_GEOMETRY" property (size)
- //Turn the QList into xcb_ewmh_coordinates_t*
- xcb_ewmh_coordinates_t array[1];
- array[0].x=geom.x(); array[0].y=geom.y();
- //Now set the property
- xcb_ewmh_set_desktop_viewport(&obj->EWMH, QX11Info::appScreen(), 1, array);
- xcb_ewmh_set_desktop_geometry(&obj->EWMH, QX11Info::appScreen(), geom.width(), geom.height());
-}
-
-void NativeWindowSystem::setRoot_desktopWorkarea(QList<QRect> list){
- //Convert to the XCB/EWMH data structures
- xcb_ewmh_geometry_t array[list.length()];
- for(int i=0; i<list.length(); i++){
- array[i].x = list[i].x(); array[i].y = list[i].y();
- array[i].width = list[i].width(); array[i].height = list[i].height();
- }
- //Now set the property
- xcb_ewmh_set_workarea(&obj->EWMH, QX11Info::appScreen(), list.length(), array);
-}
-
-void NativeWindowSystem::setRoot_activeWindow(WId win){
- /*xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), win);
- //Also send the active window a message to take input focus
- //Send the window a WM_TAKE_FOCUS message
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = win;
- event.type = obj->ATOMS["WM_PROTOCOLS"];
- event.data.data32[0] = obj->ATOMS["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_flush(QX11Info::connection());*/
-}
-
-int NativeWindowSystem::currentWorkspace(){
- xcb_get_property_cookie_t cookie = xcb_ewmh_get_current_desktop_unchecked(&obj->EWMH, QX11Info::appScreen());
- uint32_t num = 0;
- if(1==xcb_ewmh_get_current_desktop_reply(&obj->EWMH, cookie, &num, NULL) ){
- return num;
- }else{
- return 0;
- }
-}
-
-//NativeWindowEventFilter interactions
-void NativeWindowSystem::NewWindowDetected(WId id){
- //Make sure this can be managed first
- if(findWindow(id, false) != 0){ findWindow(id,false)->setProperty(NativeWindow::Visible, true, true); return; } //already managed
- xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), id);
- xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL);
- if(attr == 0){ return; } //could not get attributes of window
- if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage)
- free(attr);
- //Now go ahead and create/populate the container for this window
- NativeWindow *win = new NativeWindow(id);
- //Register for events from this window
- registerClientEvents(win->id());
- NWindows << win;
- UpdateWindowProperties(win, NativeWindow::allProperties());
- qDebug() << "New Window [& associated ID's]:" << win->id() << win->property(NativeWindow::Name).toString();
- //Now setup the connections with this window
- connect(win, SIGNAL(RequestClose(WId)), this, SLOT(RequestClose(WId)) );
- connect(win, SIGNAL(RequestKill(WId)), this, SLOT(RequestKill(WId)) );
- connect(win, SIGNAL(RequestPing(WId)), this, SLOT(RequestPing(WId)) );
- connect(win, SIGNAL(RequestReparent(WId, WId, QPoint)), this, SLOT(RequestReparent(WId, WId, QPoint)) );
- connect(win, SIGNAL(RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>)), this, SLOT(RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>)) );
- emit NewWindowAvailable(win);
-}
-
-void NativeWindowSystem::NewTrayWindowDetected(WId id){
- //Make sure this can be managed first
- if(findTrayWindow(id) != 0){ return; } //already managed
- xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), id);
- xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL);
- if(attr == 0){ return; } //could not get attributes of window
- if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage)
- free(attr);
- //Register for events from this window
- #define TRAY_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \
- XCB_EVENT_MASK_BUTTON_RELEASE | \
- XCB_EVENT_MASK_POINTER_MOTION | \
- XCB_EVENT_MASK_BUTTON_MOTION | \
- XCB_EVENT_MASK_EXPOSURE | \
- XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \
- XCB_EVENT_MASK_ENTER_WINDOW)
-
- uint32_t value_list[1] = {TRAY_WIN_EVENT_MASK};
- xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list);
- //Now go ahead and create/populate the container for this window
- NativeWindow *win = new NativeWindow(id);
- TWindows << win;
- UpdateWindowProperties(win, NativeWindow::allProperties());
- emit NewTrayWindowAvailable(win);
-}
-
-void NativeWindowSystem::WindowCloseDetected(WId id){
- NativeWindow *win = findWindow(id, false);
- //qDebug() << "Got Window Closed" << id << win;
- //qDebug() << "Old Window List:" << NWindows.length();
- if(win!=0){
- NWindows.removeAll(win);
- //RequestReparent(id, QX11Info::appRootWindow(), QPoint(0,0));
- win->emit WindowClosed(id);
- //qDebug() << "Visible Window Closed!!!";
- //win->deleteLater();
- }else{
- win = findTrayWindow(id);
- if(win!=0){
- TWindows.removeAll(win);
- win->emit WindowClosed(id);
- win->deleteLater();
- }
- }
- //qDebug() << " - Now:" << NWindows.length();
-}
-
-void NativeWindowSystem::WindowPropertyChanged(WId id, NativeWindow::Property prop){
- //NOTE: This is triggered by the NativeEventFilter - not by changes to the NativeWindow objects themselves
- NativeWindow *win = findWindow(id, prop!=NativeWindow::Visible);
- if(win==0){ win = findTrayWindow(id); }
- if(win!=0){
- UpdateWindowProperties(win, QList<NativeWindow::Property>() << prop);
- }else if(prop != 0){
- //Could not find the window for a specific property with an undefined value
- // - update this property for all the windows just in case
- for(int i=0; i<NWindows.length(); i++){
- UpdateWindowProperties( NWindows[i], QList<NativeWindow::Property>() << prop);
- }
- }
-}
-
-void NativeWindowSystem::WindowPropertiesChanged(WId id, QList<NativeWindow::Property> props){
- //NOTE: This is triggered by the NativeEventFilter - not by changes to the NativeWindow objects themselves
- NativeWindow *win = findWindow(id);
- if(win==0){ win = findTrayWindow(id); }
- if(win!=0){
- UpdateWindowProperties(win, props);
- }else{
- //Could not find the window for a specific property with an undefined value
- // - update this property for all the windows just in case
- for(int i=0; i<NWindows.length(); i++){
- UpdateWindowProperties( NWindows[i], props);
- }
- }
-}
-
-void NativeWindowSystem::WindowPropertyChanged(WId id, NativeWindow::Property prop, QVariant val){
- NativeWindow *win = findWindow(id,prop!=NativeWindow::Visible);
- if(win==0){ win = findTrayWindow(id); }
- if(win!=0){
- win->setProperty(prop, val);
- }
-}
-
-void NativeWindowSystem::WindowPropertiesChanged(WId id, QList<NativeWindow::Property> props, QList<QVariant> vals){
- NativeWindow *win = findWindow(id);
- if(win==0){ win = findTrayWindow(id); }
- if(win!=0){
- for(int i=0; i<props.length() && i<vals.length(); i++){ win->setProperty(props[i], vals[i]); }
- }
-}
-
-void NativeWindowSystem::RequestPropertyChange(WId id, NativeWindow::Property prop, QVariant val){
- //This is just a simplified version of the multiple-property function
- RequestPropertiesChange(id, QList<NativeWindow::Property>() << prop, QList<QVariant>() << val);
-}
-
-void NativeWindowSystem::RequestPropertiesChange(WId win, QList<NativeWindow::Property> props, QList<QVariant> vals){
- //Find the window object associated with this id
- bool istraywin = false; //just in case we care later if it is a tray window or a regular window
- NativeWindow *WIN = findWindow(win);
- if(WIN==0){ istraywin = true; WIN = findTrayWindow(win); }
- if(WIN==0){ return; } //invalid window ID - no longer available
- //Now make any changes as needed
- ChangeWindowProperties(WIN, props, vals);
-}
-
-void NativeWindowSystem::GotPong(WId id){
- if(waitingForPong.contains(id)){
- waitingForPong.remove(id);
- }
- if(waitingForPong.isEmpty() && pingTimer!=0){ pingTimer->stop(); }
-}
-
-void NativeWindowSystem::NewKeyPress(int keycode, WId win){
- emit NewInputEvent();
- if(screenLocked){ return; }
- Qt::Key key = KeycodeToQt(keycode);
- if(key!=Qt::Key_unknown){ emit KeyPressDetected(win, key); }
-}
-
-void NativeWindowSystem::NewKeyRelease(int keycode, WId win){
- emit NewInputEvent();
- if(screenLocked){ return; }
- Qt::Key key = KeycodeToQt(keycode);
- if(key!=Qt::Key_unknown){ emit KeyReleaseDetected(win, key); }
-}
-
-void NativeWindowSystem::NewMousePress(int buttoncode, WId win){
- emit NewInputEvent();
- if(screenLocked){ return; }
- emit MousePressDetected(win, MouseToQt(buttoncode));
-}
-
-void NativeWindowSystem::NewMouseRelease(int buttoncode, WId win){
- emit NewInputEvent();
- if(screenLocked){ return; }
- emit MouseReleaseDetected(win, MouseToQt(buttoncode));
-}
-
-void NativeWindowSystem::CheckDamageID(WId win){
- for(int i=0; i<NWindows.length(); i++){
- if(NWindows[i]->damageId() == win || NWindows[i]->id() == win || NWindows[i]->frameId()==win){
- NWindows[i]->emit VisualChanged();
- //qDebug() << "Got DAMAGE Event";
- return;
- }
- }
- NativeWindow *WIN = findTrayWindow(win);
- if(WIN!=0){
- UpdateWindowProperties(WIN, QList<NativeWindow::Property>() << NativeWindow::Icon);
- }
-}
-
-// === PRIVATE SLOTS ===
-//These are the slots which are built-in and automatically connected when a new NativeWindow is created
-
-void NativeWindowSystem::RequestClose(WId win){
- //Send the window a WM_DELETE_WINDOW message
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = win;
- event.type = obj->ATOMS.value("WM_PROTOCOLS");
- event.data.data32[0] = obj->ATOMS.value("WM_DELETE_WINDOW");
- 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_flush(QX11Info::connection());
-}
-
-void NativeWindowSystem::RequestKill(WId win){
- xcb_kill_client(QX11Info::connection(), win);
-}
-
-void NativeWindowSystem::RequestPing(WId win){
- waitingForPong.insert(win, QDateTime::currentDateTime().addSecs(5) );
- xcb_ewmh_send_wm_ping(&obj->EWMH, win, XCB_CURRENT_TIME);
- if(pingTimer==0){
- pingTimer = new QTimer(this);
- pingTimer->setInterval(2000); //2seconds
- connect(pingTimer, SIGNAL(timeout()), this, SLOT(checkPings()) );
- }
- pingTimer->start();
-}
-
-void NativeWindowSystem::RequestReparent(WId win, WId container, QPoint relorigin){
- NativeWindow *WIN = findWindow(win);
- if(WIN==0){ return; } //could not find corresponding window structure
-//Reparent the window into the container
- xcb_reparent_window(QX11Info::connection(), win, container, relorigin.x(), relorigin.y());
- //xcb_map_window(QX11Info::connection(), win);
-
- //Now send the embed event to the app
- //qDebug() << " - send _XEMBED event";
- xcb_client_message_event_t event;
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.window = win;
- event.type = obj->ATOMS["_XEMBED"]; //_XEMBED
- event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime;
- event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY
- event.data.data32[2] = 0;
- event.data.data32[3] = container; //WID of the container
- 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);
-
- //Now setup any redirects and return
- //this->SelectInput(win, true); //Notify of structure changes
- registerClientEvents(win);
- //xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]);
-
- //Now map the window (will be a transparent child of the container)
- xcb_map_window(QX11Info::connection(), win);
- xcb_map_window(QX11Info::connection(), container);
- //Now create/register the damage handler
- // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore)
- // -- Retested 6/29/17 (no change) Ken Moore
- //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer
- //xcb_damage_create(QX11Info::connection(), dmgID, win, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
- // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself).
- Damage dmgID = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles);
- WIN->addDamageID( (uint) dmgID); //save this for later
- //qDebug() << " - Done";
- //return ( (uint) dmgID );
-}
-/*
- xcb_reparent_window(QX11Info::connection(), client, parent, relorigin.x(), relorigin.y());
-
- //Now ensure that we still get event for these windows
- registerClientEvents(client); //make sure we re-do this after reparenting
- registerClientEvents(parent);
- xcb_map_window(QX11Info::connection(), parent);
-}*/
diff --git a/src-qt5/src-cpp/NativeWindowSystem.h b/src-qt5/src-cpp/NativeWindowSystem.h
deleted file mode 100644
index b67ecc94..00000000
--- a/src-qt5/src-cpp/NativeWindowSystem.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//===========================================
-// 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"
-#include <QDateTime>
-#include <QTimer>
-#include <QDebug>
-
-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, bool checkRelated = true);
-
- NativeWindow* findTrayWindow(WId id);
-
- //Now define a simple private_objects class so that each implementation
- // has a storage container for defining/placing private objects as needed
- class p_objects;
- p_objects* obj;
-
- //Internal timers/variables for managing pings
- QTimer *pingTimer;
- QHash<WId, QDateTime> waitingForPong;
- void checkPings(){
- QDateTime cur = QDateTime::currentDateTime();
- QList<WId> waiting = waitingForPong.keys();
- for(int i=0; i<waiting.length(); i++){
- if(waitingForPong.value(waiting[i]) < cur){
- waitingForPong.remove(waiting[i]); //Timeout on this window
- if(waitingForPong.isEmpty() && pingTimer!=0){ pingTimer->stop(); }
- NativeWindow *win = findWindow(waiting[i]);
- if(win==0){ win = findTrayWindow(waiting[i]); }
- if(win!=0){ win->emit WindowNotResponding(waiting[i]); }
- }
- }
- }
-
- // 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);
- void ChangeWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props, QList<QVariant> vals);
-
- //Generic private variables
- bool screenLocked;
-
-public:
- //enum Property{ None, CurrentWorkspace, Workspaces, VirtualRoots, WorkAreas };
- enum MouseButton{NoButton, LeftButton, RightButton, MidButton, BackButton, ForwardButton, TaskButton, WheelUp, WheelDown, WheelLeft, WheelRight};
-
- NativeWindowSystem();
- ~NativeWindowSystem();
-
- //Overarching start/stop functions
- bool start();
- void stop();
-
- //General-purpose listing functions
- QList<NativeWindow*> currentWindows(){ return NWindows; }
- QList<NativeWindow*> currentTrayWindows(){ return TWindows; }
-
- //Small simplification functions
- static Qt::Key KeycodeToQt(int keycode);
- static NativeWindowSystem::MouseButton MouseToQt(int button);
-
-public slots:
- //These are the slots which are typically only used by the desktop system itself or the NativeWindowEventFilter
-
- //This is called by the lock screen to keep the NWS aware of the current status
- // it is **NOT** the function to call for the user to actually lock the session (that is in the screensaver/lockscreen class)
- void ScreenLockChanged(bool lock){
- screenLocked = lock;
- }
-
- //Root Window property registrations
- void RegisterVirtualRoot(WId);
- void setRoot_supportedActions();
- void setRoot_numberOfWorkspaces(QStringList names);
- void setRoot_currentWorkspace(int);
- void setRoot_clientList(QList<WId>, bool stackorder = false);
- void setRoot_desktopGeometry(QRect);
- void setRoot_desktopWorkarea(QList<QRect>);
- void setRoot_activeWindow(WId);
-
- // - Workspaces
- int currentWorkspace();
- //void GoToWorkspace(int);
-
-
- //NativeWindowEventFilter interactions
- void NewWindowDetected(WId); //will automatically create the new NativeWindow object
- void NewTrayWindowDetected(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 WindowPropertiesChanged(WId, QList<NativeWindow::Property>);
- void WindowPropertyChanged(WId, NativeWindow::Property, QVariant); //will save that property/value to the right object
- void WindowPropertiesChanged(WId, QList<NativeWindow::Property>, QList<QVariant>);
- void RequestPropertyChange(WId, NativeWindow::Property, QVariant);
- void RequestPropertiesChange(WId, QList<NativeWindow::Property>, QList<QVariant>);
- void GotPong(WId);
-
- void NewKeyPress(int keycode, WId win = 0);
- void NewKeyRelease(int keycode, WId win = 0);
- void NewMousePress(int buttoncode, WId win = 0);
- void NewMouseRelease(int buttoncode, WId win = 0);
- void CheckDamageID(WId);
-
-private slots:
- //These are the slots which are built-in and automatically connected when a new NativeWindow is created
- void RequestClose(WId);
- void RequestKill(WId);
- void RequestPing(WId);
- void RequestReparent(WId, WId, QPoint); //client, parent, relative origin point in parent
-
-signals:
- void NewWindowAvailable(NativeWindow*);
- void NewTrayWindowAvailable(NativeWindow*);
- void NewInputEvent(); //a mouse or keypress was detected (lock-state independent);
- void KeyPressDetected(WId, Qt::Key); //only emitted if lockstate = false
- void KeyReleaseDetected(WId, Qt::Key); //only emitted if lockstate = false
- void MousePressDetected(WId, NativeWindowSystem::MouseButton); //only emitted if lockstate = false
- void MouseReleaseDetected(WId, NativeWindowSystem::MouseButton); //only emitted if lockstate = false
-
-};
-
-#endif
diff --git a/src-qt5/src-cpp/framework-OSInterface-FreeBSD.cpp b/src-qt5/src-cpp/framework-OSInterface-FreeBSD.cpp
new file mode 100644
index 00000000..247b1bdb
--- /dev/null
+++ b/src-qt5/src-cpp/framework-OSInterface-FreeBSD.cpp
@@ -0,0 +1,245 @@
+//===========================================
+// Lumina desktop source code
+// Copyright (c) 2017, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// FreeBSD/TrueOS specific OS Interactions
+//===========================================
+// USEFUL INTERNAL FUNCTIONS:
+//----------------------------------------------
+// bool verifyAppOrBin(QString chk)
+//===========================================
+#include <framework-OSInterface.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+
+// = Battery =
+bool OSInterface::OS_batteryAvailable(){
+ static int bat_avail = -1; //this will not change during a single session - keep later calls fast
+ if(bat_avail < 0){
+ int val = getCmdOutput("apm -l").join("").toInt();
+ bat_avail = ((val >= 0 && val <= 100) ? 1 : 0 );
+ }
+ return (bat_avail==1);
+}
+
+float OSInterface::OS_batteryCharge(){
+ int charge = getCmdOutput("apm -l").join("").toInt();
+ if(charge > 100){ charge = -1; } //invalid charge
+ return charge;
+}
+
+bool OSInterface::OS_batteryCharging(){
+ return (getCmdOutput("apm -a").join("").simplified() == "1");
+}
+
+double OSInterface::OS_batterySecondsLeft(){ //Returns: estimated number of seconds remaining
+ return getCmdOutput("apm -t").join("").toDouble();
+}
+
+// = Volume =
+bool OSInterface::OS_volumeSupported(){ return true; }
+int OSInterface::OS_volume(){
+ int out = -1;
+ /*bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty();
+ if(remoteSession){
+ QStringList info = getCmdOutput("pactl list short sinks");
+ qDebug() << "Got PA sinks:" << info;
+ out = 50; //TEMPORARY - still need to write up the info parsing
+ }else{*/
+ //probe the system for the current volume (other utils could be changing it)
+ QString info = getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines
+ if(!info.isEmpty()){
+ int L = info.section(":",1,1).toInt();
+ int R = info.section(":",2,2).toInt();
+ if(L>R){ out = L; }
+ else{ out = R; }
+ }
+ //} //end of Remote Session check
+ return out;
+}
+
+bool OSInterface::OS_setVolume(int percent){
+ if(percent<0){percent=0;}
+ else if(percent>100){percent=100;}
+ /*bool remoteSession = !QString(getenv("PICO_CLIENT_LOGIN")).isEmpty();
+ if(remoteSession){
+ runCmd(QString("pactl set-sink-volume @DEFAULT_SINK@ ")+QString::number(percent)+"%");
+ }else{*/
+ QString info = getCmdOutput("mixer -S vol").join(":").simplified(); //ignores any other lines
+ if(!info.isEmpty()){
+ int L = info.section(":",1,1).toInt();
+ int R = info.section(":",2,2).toInt();
+ int diff = L-R;
+ if((percent == L) && (L==R)){ return false; } //already set to that volume
+ if(diff<0){ R=percent; L=percent+diff; } //R Greater
+ else{ L=percent; R=percent-diff; } //L Greater or equal
+ //Check bounds
+ if(L<0){L=0;}else if(L>100){L=100;}
+ if(R<0){R=0;}else if(R>100){R=100;}
+ //Run Command
+ return (0==runCmd("mixer vol "+QString::number(L)+":"+QString::number(R)) );
+ }
+ //} //end of Remote Session check
+ return false;
+}
+
+// = Network Information =
+QString OSInterface::OS_networkTypeFromDeviceName(QString name){
+ //Return options: wifi, wired, cell, cell-2G, cell-3G, cell-4G
+ QString type = "wired";
+ if(name.startsWith("wlan")){ type = "wifi"; }
+ //Not sure about cell connections . Probably still treated as wifi devices (wlan*)
+ return type;
+}
+
+float OSInterface::OS_networkStrengthFromDeviceName(QString name){
+ //NOTE: This will only run for non-wired devices (wifi, cell[-*])
+ // Step 1 : Figure out which access point is currently connected
+ QStringList info = getCmdOutput("ifconfig", QStringList() << name).filter("bssid");
+ if(info.isEmpty()){ return -1; }
+ QString bssid = info.first().section("bssid ",1,-1).section(" ",0,0);
+ // Step 2: Scan access point to get signal/noise
+ info = getCmdOutput("ifconfig", QStringList() << name << "list" << "scan").filter(bssid);
+ if(info.isEmpty()){ return -1; }
+ QString signoise =info.first().section(" ", 4,4, QString::SectionSkipEmpty).simplified();
+ int sig = signoise.section(":",0,0).toInt();
+ int noise = signoise.section(":",1,1).toInt();
+ // Step 3: Turn signal/noise ratio into a percentage
+ int perc = qAbs(sig - noise) * 4;
+ return perc; //percentage
+}
+
+// = Media Shortcuts =
+QStringList OSInterface::OS_mediaDirectories(){ return QStringList() << "/media"; } //directory where XDG shortcuts are placed for interacting with media (local/remote)
+
+// = Updates =
+bool OSInterface::OS_updatesSupported(){ return verifyAppOrBin("pc-updatemanager"); }
+
+bool OSInterface::OS_updatesAvailable(){ return QFile::exists("/tmp/.trueos-update-staged"); }
+QString OSInterface::OS_updateDetails(){ return readFile("/tmp/.trueos-update-staged"); } //Information about any available updates
+
+bool OSInterface::OS_updatesRunning(){ return (runCmd("pgrep -F /tmp/.updateInProgress")==0); }
+QString OSInterface::OS_updateLog(){ return QString(); } //Information about any currently-running update
+
+//Note: Because the second-stage updates on TrueOS actually happen on reboot, we never see a "finished" update
+bool OSInterface::OS_updatesFinished(){ return false; }
+QString OSInterface::OS_updateResults(){ return QString(); } //Information about any finished update
+
+void OSInterface::OS_startUpdates(){ runCmd("pc-updatemanager", QStringList() << "startupdate"); } //start stage 2 on reboot
+bool OSInterface::OS_updateOnlyOnReboot(){ return true; } //Should the startUpdates function be called only when rebooting the system?
+bool OSInterface::OS_updateCausesReboot(){ return true; }
+
+QDateTime OSInterface::OS_lastUpdate(){ return QDateTime(); } //The date/time of the previous updates
+QString OSInterface::OS_lastUpdateResults(){ return QString(); } //Information about the previously-finished update
+
+// = System Power =
+bool OSInterface::OS_canReboot(){
+ int ret = eaccess("/sbin/shutdown", X_OK);
+ return (ret==0);
+}
+void OSInterface::OS_startReboot(){ runCmd("/sbin/shutdown", QStringList() << "-ro" << "now"); }
+
+bool OSInterface::OS_canShutdown(){
+ int ret = eaccess("/sbin/shutdown", X_OK);
+ return (ret==0);
+}
+void OSInterface::OS_startShutdown(){ runCmd("/sbin/shutdown", QStringList() << "-po" << "now"); }
+
+bool OSInterface::OS_canSuspend(){
+ int ret = eaccess("/usr/sbin/acpiconf", X_OK);
+ return (ret==0);
+}
+void OSInterface::OS_startSuspend(){ runCmd("zzz"); } //zzz runs "acpiconf -s <suspend state>"
+
+// = Screen Brightness =
+bool OSInterface::OS_brightnessSupported(){
+//First run a quick check to ensure this is not a VirtualBox VM (no brightness control)
+ static int goodsys = -1; //This will not change over time - only check/set once
+ if(goodsys<0){
+ //Make sure we are not running in VirtualBox (does not work in a VM)
+ QStringList info = getCmdOutput("pciconf -lv");
+ if( info.filter("VirtualBox", Qt::CaseInsensitive).isEmpty() ){ goodsys = 1; }
+ else{ goodsys = 0; } //not a good system
+ }
+ if(goodsys!=1){ return false; } //go ahead and stop here - not a good system
+ QStringList tools; tools << "intel_backlight" << "xbrightness";
+ bool ok = false;
+ for(int i=0; i<tools.length() && !ok; i++){ ok = verifyAppOrBin(tools[i]); }
+ return ok;
+}
+
+int OSInterface::OS_brightness(){
+ //return percentage: 0-100 with -1 for errors
+ QStringList tools; tools << "intel_backlight" << "xbrightness";
+ //NOTE: xbacklight does not have a way to return the current brightness
+ int num = -1;
+ for(int i=0; i<tools.length() && num<0; i++){
+ if(!verifyAppOrBin(tools[i])){ continue; }
+ switch(i){
+ case 0: //intel_backlight
+ num = getCmdOutput("intel_backlight").join("").section("%",0,0).section(":",1,1).simplified().toInt();
+ break;
+ default:
+ num = -1;
+ }
+ }
+ if(num>100){ num=100; } //quick verification of upper limit
+ else if(num<-1){ num = -1; } //something really messed up - return the error code
+ return num;
+}
+
+bool OSInterface::OS_setBrightness(int percent){
+ QStringList tools; tools << "intel_backlight" << "xbrightness";
+ for(int i=0; i<tools.length(); i++){
+ if(!verifyAppOrBin(tools[i])){ continue; }
+ QStringList args;
+ switch(i){
+ case 0: //intel_backlight
+ args << QString::number(percent);
+ break;
+ case 1: //xbrightness
+ args << QString::number( qRound( (percent/100.0)*65535) ); //xbrightness has a scale of 0-65535
+ break;
+ }
+ return (0 == runCmd(tools[i], args) );
+ }
+ return false;
+}
+
+// = System Status Monitoring
+bool OSInterface::OS_cpuSupported(){ return false; }
+QList<int> OSInterface::OS_cpuPercentage(){ return QList<int>(); } // (one per CPU) percentage: 0-100 with empty list for errors
+QStringList OSInterface::OS_cpuTemperatures(){ return QStringList(); } // (one per CPU) Temperature of CPU ("50C" for example)
+
+bool OSInterface::OS_memorySupported(){ return false; }
+int OSInterface::OS_memoryUsedPercentage(){ return -1; } //percentage: 0-100 with -1 for errors
+QString OSInterface::OS_memoryTotal(){ return QString(); } //human-readable form - does not tend to change within a session
+QStringList OSInterface::OS_diskIO(){ return QStringList(); } //Returns list of current read/write stats for each device
+
+bool OSInterface::OS_diskSupported(){ return false; }
+int OSInterface::OS_fileSystemPercentage(QString dir){ return -1; } //percentage of capacity used: 0-100 with -1 for errors
+QString OSInterface::OS_fileSystemCapacity(QString dir){ return QString(); } //human-readable form - total capacity
+
+// = OS-Specific Utilities =
+QString OSInterface::controlPanelShortcut(){ return "pccontrol.desktop"; } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+QString OSInterface::audioMixerShortcut(){ return "pc-mixer -notray"; } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+QString OSInterface::appStoreShortcut(){ return "appcafe.desktop"; } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+QString OSInterface::networkManagerUtility(){ return "pc-netmanager.desktop"; } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+
+//FileSystemWatcher slots (optional - re-implement only if needed/used by this OS)
+void OSInterface::watcherFileChanged(QString){} //any additional parsing for files that are watched
+void OSInterface::watcherDirChanged(QString dir){ //any additional parsing for watched directories
+ if(handleMediaDirChange(dir)){ return; } //auto-handled media directories
+}
+
+//IO Device slots (optional - implement only if needed/used by this OS)
+void OSInterface::iodeviceReadyRead(){}
+void OSInterface::iodeviceAboutToClose(){}
+
+void OSInterface::netRequestFinished(QNetworkReply*){}
+void OSInterface::netSslErrors(QNetworkReply*, const QList<QSslError>&){}
diff --git a/src-qt5/src-cpp/framework-OSInterface-template.cpp b/src-qt5/src-cpp/framework-OSInterface-template.cpp
index 972e02e0..c9c7775a 100644
--- a/src-qt5/src-cpp/framework-OSInterface-template.cpp
+++ b/src-qt5/src-cpp/framework-OSInterface-template.cpp
@@ -4,147 +4,95 @@
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
+// USEFUL INTERNAL FUNCTIONS: (See framework-OSInterface.h for all possibilities);
+//----------------------------------------------
+// bool verifyAppOrBin(QString chk) : Returns true is the check is a valid binary or application (*.desktop)
+// int runCmd(QString command, QStringList arguments) : return code of command is returned
+// QStringList getCmdOutput(QString command, QStringList arguments) : returns standard output of command
+//===========================================
#include <framework-OSInterface.h>
-#include <QNetworkConfiguration>
-#include <QNetworkInterface>
-
-//Start/stop interface watchers/notifications
-void OSInterface::start(){
- setupMediaWatcher(); //will create/connect the filesystem watcher automatically
- setupNetworkManager();
-}
-
-void OSInterface::stop(){
- if(isRunning()){
- watcher->deleteLater();
- watcher = 0;
- }
-}
-
-bool OSInterface::isRunning(){ return (watcher!=0); } //status of the object - whether it has been started yet
// = Battery =
-bool OSInterface::batteryAvailable(){ return false; }
-float OSInterface::batteryCharge(){ return -1; }
-bool OSInterface::batteryCharging(){ return false; }
-double OSInterface::batterySecondsLeft(){ return -1; }
+bool OSInterface::OS_batteryAvailable(){ return false; }
+float OSInterface::OS_batteryCharge(){ return -1; }
+bool OSInterface::OS_batteryCharging(){ return false; }
+double OSInterface::OS_batterySecondsLeft(){ return -1; }
// = Volume =
-bool OSInterface::volumeAvailable(){ return false; }
-int OSInterface::volume(){ return -1; }
-void OSInterface::setVolume(int){}
+bool OSInterface::OS_volumeSupported(){ return false; }
+int OSInterface::OS_volume(){ return -1; }
+bool OSInterface::OS_setVolume(int){ return false;}
// = Network Information =
-bool OSInterface::networkAvailable(){
- if(INFO.contains("netaccess/available")){ return INFO.value("netaccess/available").toBool(); }
- return false;
-}
-
-QString OSInterface::networkType(){
- if(INFO.contains("netaccess/type")){ return INFO.value("netaccess/type").toString(); } //"wifi", "wired", or "cell"
+QString OSInterface::OS_networkTypeFromDeviceName(QString name){
+ //Return options: wifi, wired, cell, cell-2G, cell-3G, cell-4G
return "";
}
-float OSInterface::networkStrength(){ return -1; } //percentage. ("wired" type should always be 100%)
-
-QString OSInterface::networkHostname(){
- return QHostInfo::localHostName();
-}
-
-QHostAddress OSInterface::networkAddress(){
- QString addr;
- if(INFO.contains("netaccess/address")){ addr = INFO.value("netaccess/address").toString(); }
- return QHostAddress(addr);
+float OSInterface::OS_networkStrengthFromDeviceName(QString name){
+ //NOTE: This will only run for non-wired devices (wifi, cell[-*])
+ return -1; //percentage
}
-// = Network Modification =
// = Media Shortcuts =
-QStringList OSInterface::mediaDirectories(){ return QStringList() << "/media"; } //directory where XDG shortcuts are placed for interacting with media (local/remote)
-QStringList OSInterface::mediaShortcuts(){ return autoHandledMediaFiles(); } //List of currently-available XDG shortcut file paths
+QStringList OSInterface::OS_mediaDirectories(){ return QStringList() << "/media"; } //directory where XDG shortcuts are placed for interacting with media (local/remote)
// = Updates =
-bool OSInterface::updatesAvailable(){ return false; }
-QString OSInterface::updateDetails(){ return QString(); } //Information about any available updates
-bool OSInterface::updatesRunning(){ return false; }
-QString OSInterface::updateLog(){ return QString(); } //Information about any currently-running update
-bool OSInterface::updatesFinished(){ return false; }
-QString OSInterface::updateResults(){ return QString(); } //Information about any finished update
-void OSInterface::startUpdates(){}
-bool OSInterface::updateOnlyOnReboot(){ return false; } //Should the startUpdates function be called only when rebooting the system?
-QDateTime OSInterface::lastUpdate(){ return QDateTime(); } //The date/time of the previous updates
-QString OSInterface::lastUpdateResults(){ return QString(); } //Information about the previously-finished update
+bool OSInterface::OS_updatesSupported(){ return false; }
+bool OSInterface::OS_updatesAvailable(){ return false; }
+QString OSInterface::OS_updateDetails(){ return QString(); } //Information about any available updates
+bool OSInterface::OS_updatesRunning(){ return false; }
+QString OSInterface::OS_updateLog(){ return QString(); } //Information about any currently-running update
+bool OSInterface::OS_updatesFinished(){ return false; }
+QString OSInterface::OS_updateResults(){ return QString(); } //Information about any finished update
+void OSInterface::OS_startUpdates(){}
+bool OSInterface::OS_updateOnlyOnReboot(){ return false; } //Should the startUpdates function be called only when rebooting the system?
+bool OSInterface::OS_updateCausesReboot(){ return false; }
+QDateTime OSInterface::OS_lastUpdate(){ return QDateTime(); } //The date/time of the previous updates
+QString OSInterface::OS_lastUpdateResults(){ return QString(); } //Information about the previously-finished update
// = System Power =
-bool OSInterface::canReboot(){ return false; }
-void OSInterface::startReboot(){}
-bool OSInterface::canShutdown(){ return false; }
-void OSInterface::startShutdown(){}
-bool OSInterface::canSuspend(){ return false; }
-void OSInterface::startSuspend(){}
+bool OSInterface::OS_canReboot(){ return false; }
+void OSInterface::OS_startReboot(){}
+bool OSInterface::OS_canShutdown(){ return false; }
+void OSInterface::OS_startShutdown(){}
+bool OSInterface::OS_canSuspend(){ return false; }
+void OSInterface::OS_startSuspend(){}
// = Screen Brightness =
-int OSInterface::brightness(){ return -1; } //percentage: 0-100 with -1 for errors
-void OSInterface::setBrightness(int){}
+bool OSInterface::OS_brightnessSupported(){ return false; }
+int OSInterface::OS_brightness(){ return -1; } //percentage: 0-100 with -1 for errors
+bool OSInterface::OS_setBrightness(int){ return false; }
// = System Status Monitoring
-QList<int> OSInterface::cpuPercentage(){ return QList<int>(); } // (one per CPU) percentage: 0-100 with empty list for errors
-QStringList OSInterface::cpuTemperatures(){ return QStringList(); } // (one per CPU) Temperature of CPU ("50C" for example)
-int OSInterface::memoryUsedPercentage(){ return -1; } //percentage: 0-100 with -1 for errors
-QString OSInterface::memoryTotal(){ return QString(); } //human-readable form - does not tend to change within a session
-QStringList OSInterface::diskIO(){ return QStringList(); } //Returns list of current read/write stats for each device
-int OSInterface::fileSystemPercentage(QString dir){ return -1; } //percentage of capacity used: 0-100 with -1 for errors
-QString OSInterface::fileSystemCapacity(QString dir){ return QString(); } //human-readable form - total capacity
+bool OSInterface::OS_cpuSupported(){ return false; }
+QList<int> OSInterface::OS_cpuPercentage(){ return QList<int>(); } // (one per CPU) percentage: 0-100 with empty list for errors
+QStringList OSInterface::OS_cpuTemperatures(){ return QStringList(); } // (one per CPU) Temperature of CPU ("50C" for example)
+
+bool OSInterface::OS_memorySupported(){ return false; }
+int OSInterface::OS_memoryUsedPercentage(){ return -1; } //percentage: 0-100 with -1 for errors
+QString OSInterface::OS_memoryTotal(){ return QString(); } //human-readable form - does not tend to change within a session
+QStringList OSInterface::OS_diskIO(){ return QStringList(); } //Returns list of current read/write stats for each device
+
+bool OSInterface::OS_diskSupported(){ return false; }
+int OSInterface::OS_fileSystemPercentage(QString dir){ return -1; } //percentage of capacity used: 0-100 with -1 for errors
+QString OSInterface::OS_fileSystemCapacity(QString dir){ return QString(); } //human-readable form - total capacity
// = OS-Specific Utilities =
-bool OSInterface::hasControlPanel(){ return false; }
QString OSInterface::controlPanelShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
-bool OSInterface::hasAudioMixer(){ return false; }
QString OSInterface::audioMixerShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
-bool OSInterface::hasAppStore(){ return false; }
QString OSInterface::appStoreShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+QString OSInterface::networkManagerUtility(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
-//FileSystemWatcher slots
-void OSInterface::watcherFileChanged(QString){}
-void OSInterface::watcherDirChanged(QString dir){
- if(handleMediaDirChange(dir)){ return; }
+//FileSystemWatcher slots (optional - re-implement only if needed/used by this OS)
+void OSInterface::watcherFileChanged(QString){} //any additional parsing for files that are watched
+void OSInterface::watcherDirChanged(QString dir){ //any additional parsing for watched directories
+ if(handleMediaDirChange(dir)){ return; } //auto-handled media directories
}
-//IO Device slots
+//IO Device slots (optional - implement only if needed/used by this OS)
void OSInterface::iodeviceReadyRead(){}
void OSInterface::iodeviceAboutToClose(){}
-//NetworkAccessManager slots
-void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility stat){
- INFO.insert("netaccess/available", stat== QNetworkAccessManager::Accessible);
- //Update all the other network status info at the same time
- QNetworkConfiguration active = netman->activeConfiguration();
- //Type of connection
- QString type;
- switch(active.bearerTypeFamily()){
- case QNetworkConfiguration::BearerEthernet: type="wired"; break;
- case QNetworkConfiguration::BearerWLAN: type="wifi"; break;
- case QNetworkConfiguration::Bearer2G: type="cell-2G"; break;
- case QNetworkConfiguration::Bearer3G: type="cell-3G"; break;
- case QNetworkConfiguration::Bearer4G: type="cell-4G"; break;
- default: type="";
- }
- INFO.insert("netaccess/type", type);
- qDebug() << "Detected Device Status:" << active.identifier() << type << stat;
- QNetworkInterface iface = QNetworkInterface::interfaceFromName(active.name());
- qDebug() << " - Configuration: Name:" << active.name() << active.bearerTypeName() << active.identifier();
- qDebug() << " - Interface: MAC Address:" << iface.hardwareAddress() << "Name:" << iface.name() << iface.humanReadableName() << iface.isValid();
- QList<QNetworkAddressEntry> addressList = iface.addressEntries();
- QStringList address;
- //NOTE: There are often 2 addresses, IPv4 and IPv6
- for(int i=0; i<addressList.length(); i++){
- address << addressList[i].ip().toString();
- }
- qDebug() << " - IP Address:" << address;
- qDebug() << " - Hostname:" << networkHostname();
- INFO.insert("netaccess/address", address.join(", "));
- emit networkStatusChanged();
-}
-
void OSInterface::netRequestFinished(QNetworkReply*){}
void OSInterface::netSslErrors(QNetworkReply*, const QList<QSslError>&){}
-void OSInterface::timerUpdate(){}
diff --git a/src-qt5/src-cpp/framework-OSInterface.h b/src-qt5/src-cpp/framework-OSInterface.h
index a173ad5a..7f51764b 100644
--- a/src-qt5/src-cpp/framework-OSInterface.h
+++ b/src-qt5/src-cpp/framework-OSInterface.h
@@ -18,6 +18,9 @@
#include <QVariant>
#include <QHash>
#include <QTimer>
+#include <QFile>
+#include <QDir>
+#include <QVariant>
#include <QIODevice>
#include <QFileSystemWatcher>
@@ -26,28 +29,39 @@
#include <QSslError>
#include <QHostInfo>
#include <QHostAddress>
+#include <QNetworkConfiguration>
+#include <QNetworkInterface>
+
+//Lumina Utils class
+//#include <LUtils.h>
class OSInterface : public QObject{
Q_OBJECT
// == QML ACCESSIBLE PROPERTIES ==
//Battery
- Q_PROPERTY( float batteryCharge READ batteryCharge NOTIFY batteryChargeChanged)
- Q_PROPERTY( bool batteryCharging READ batteryCharging NOTIFY batteryChargingChanged)
- Q_PROPERTY( double batterySecondsLeft READ batterySecondsLeft NOTIFY batterySecondsLeftChanged)
+ Q_PROPERTY( float batteryCharge READ batteryCharge NOTIFY batteryChanged)
+ Q_PROPERTY( bool batteryCharging READ batteryCharging NOTIFY batteryChanged)
+ Q_PROPERTY( QString batteryRemaining READ batteryRemaining NOTIFY batteryChanged)
+ Q_PROPERTY( QString batteryIcon READ batteryIcon NOTIFY batteryChanged)
+ Q_PROPERTY( QString batteryStatus READ batteryStatus NOTIFY batteryChanged)
//Volume
Q_PROPERTY( int volume READ volume WRITE setVolume NOTIFY volumeChanged)
+ Q_PROPERTY( QString volumeIcon READ volumeIcon NOTIFY volumeChanged)
//Network
Q_PROPERTY( bool networkAvailable READ networkAvailable NOTIFY networkStatusChanged)
Q_PROPERTY( QString networkType READ networkType NOTIFY networkStatusChanged)
Q_PROPERTY( float networkStrength READ networkStrength NOTIFY networkStatusChanged)
Q_PROPERTY( QString networkHostname READ networkHostname NOTIFY networkStatusChanged)
- Q_PROPERTY( QHostAddress networkAddress READ networkAddress NOTIFY networkStatusChanged)
+ Q_PROPERTY( QStringList networkAddress READ networkAddress NOTIFY networkStatusChanged)
+ Q_PROPERTY( QString networkIcon READ networkIcon NOTIFY networkStatusChanged);
+ Q_PROPERTY( QString networkStatus READ networkStatus NOTIFY networkStatusChanged);
//Media
Q_PROPERTY( QStringList mediaShortcuts READ mediaShortcuts NOTIFY mediaShortcutsChanged)
//Updates
- Q_PROPERTY( bool updatesAvailable READ updatesAvailable NOTIFY updateStatusChanged)
- Q_PROPERTY( bool updatesRunning READ updatesRunning NOTIFY updateStatusChanged)
- Q_PROPERTY( bool updatesFinished READ updatesFinished NOTIFY updateStatusChanged)
+ Q_PROPERTY( QString updateStatus READ updateStatus NOTIFY updateStatusChanged)
+ Q_PROPERTY( QString updateIcon READ updateIcon NOTIFY updateStatusChanged)
+ Q_PROPERTY( bool updateInfoAvailable READ updateInfoAvailable NOTIFY updateStatusChanged)
+
//Power options
Q_PROPERTY( bool canReboot READ canReboot NOTIFY powerAvailableChanged)
Q_PROPERTY( bool canShutdown READ canShutdown NOTIFY powerAvailableChanged)
@@ -68,33 +82,48 @@ public:
Q_INVOKABLE bool batteryAvailable();
Q_INVOKABLE float batteryCharge();
Q_INVOKABLE bool batteryCharging();
- Q_INVOKABLE double batterySecondsLeft();
+ Q_INVOKABLE QString batteryRemaining();
+ Q_INVOKABLE QString batteryIcon();
+ Q_INVOKABLE QString batteryStatus();
+
// = Volume =
- Q_INVOKABLE bool volumeAvailable();
+ Q_INVOKABLE bool volumeSupported();
Q_INVOKABLE int volume();
Q_INVOKABLE void setVolume(int);
+ Q_INVOKABLE QString volumeIcon();
+
// = Network Information =
Q_INVOKABLE bool networkAvailable();
Q_INVOKABLE QString networkType(); //"wifi", "wired", "cell", "cell-2G", "cell-3G", "cell-4G"
Q_INVOKABLE float networkStrength(); //percentage. ("wired" type should always be 100%)
+ Q_INVOKABLE QString networkIcon();
Q_INVOKABLE QString networkHostname();
- Q_INVOKABLE QHostAddress networkAddress();
+ Q_INVOKABLE QStringList networkAddress();
+ Q_INVOKABLE QString networkStatus(); //combines a bunch of the above info into a single string
+
// = Network Modification =
+ Q_INVOKABLE bool hasNetworkManager();
+ Q_INVOKABLE QString networkManagerUtility(); //binary name or *.desktop filename (if registered on the system)
// = Media Shortcuts =
Q_INVOKABLE QStringList mediaDirectories(); //directory where XDG shortcuts are placed for interacting with media (local/remote)
Q_INVOKABLE QStringList mediaShortcuts(); //List of currently-available XDG shortcut file paths
+
// = Updates =
- Q_INVOKABLE bool updatesAvailable();
+ Q_INVOKABLE bool updatesSupported(); //is thie subsystem supported for the OS?
+ Q_INVOKABLE QString updateStatus(); //Current status ["","available","running","finished"]
+ Q_INVOKABLE bool updateInfoAvailable();
+ Q_INVOKABLE QString updateIcon();
+ Q_INVOKABLE QString updateStatusInfo(); //Extra information corresponding to the current status
Q_INVOKABLE QString updateDetails(); //Information about any available updates
- Q_INVOKABLE bool updatesRunning();
Q_INVOKABLE QString updateLog(); //Information about any currently-running update
- Q_INVOKABLE bool updatesFinished();
Q_INVOKABLE QString updateResults(); //Information about any finished update
Q_INVOKABLE void startUpdates();
Q_INVOKABLE bool updateOnlyOnReboot(); //Should the startUpdates function be called only when rebooting the system?
+ Q_INVOKABLE bool updateCausesReboot(); //Does the update power-cycle the system?
Q_INVOKABLE QDateTime lastUpdate(); //The date/time of the previous updates
Q_INVOKABLE QString lastUpdateResults(); //Information about the previously-finished update
+
// = System Power =
Q_INVOKABLE bool canReboot();
Q_INVOKABLE void startReboot();
@@ -102,17 +131,26 @@ public:
Q_INVOKABLE void startShutdown();
Q_INVOKABLE bool canSuspend();
Q_INVOKABLE void startSuspend();
+
// = Screen Brightness =
+ Q_INVOKABLE bool brightnessSupported(); //is this subsystem available for the OS?
Q_INVOKABLE int brightness(); //percentage: 0-100 with -1 for errors
Q_INVOKABLE void setBrightness(int);
+
// = System Status Monitoring
+ Q_INVOKABLE bool cpuSupported(); //is this subsystem available for the OS?
Q_INVOKABLE QList<int> cpuPercentage(); // (one per CPU) percentage: 0-100 with -1 for errors
Q_INVOKABLE QStringList cpuTemperatures(); // (one per CPU) Temperature of CPU ("50C" for example)
+
+ Q_INVOKABLE bool memorySupported(); //is this subsystem available for the OS?
Q_INVOKABLE int memoryUsedPercentage(); //percentage: 0-100 with -1 for errors
Q_INVOKABLE QString memoryTotal(); //human-readable form - does not tend to change within a session
Q_INVOKABLE QStringList diskIO(); //Returns list of current read/write stats for each device
+
+ Q_INVOKABLE bool diskSupported(); //is this subsystem available for the OS?
Q_INVOKABLE int fileSystemPercentage(QString dir); //percentage of capacity used: 0-100 with -1 for errors
Q_INVOKABLE QString fileSystemCapacity(QString dir); //human-readable form - total capacity
+
// = OS-Specific Utilities =
Q_INVOKABLE bool hasControlPanel();
Q_INVOKABLE QString controlPanelShortcut(); //relative *.desktop shortcut name (Example: "some_utility.desktop")
@@ -121,10 +159,63 @@ public:
Q_INVOKABLE bool hasAppStore();
Q_INVOKABLE QString appStoreShortcut(); //relative *.desktop shortcut name (Example: "some_utility.desktop")
+
+ // = DIRECT OS INTERACTIONS = (properties above are cached/gated)
+ // = Battery =
+ bool OS_batteryAvailable();
+ float OS_batteryCharge();
+ bool OS_batteryCharging();
+ double OS_batterySecondsLeft();
+ // = Volume =
+ bool OS_volumeSupported();
+ int OS_volume();
+ bool OS_setVolume(int);
+ // = Network Information =
+ QString OS_networkTypeFromDeviceName(QString name);
+ float OS_networkStrengthFromDeviceName(QString name);
+ // = Media Shortcuts =
+ QStringList OS_mediaDirectories();
+ // = Updates =
+ bool OS_updatesSupported();
+ bool OS_updatesAvailable();
+ QString OS_updateDetails();
+ bool OS_updatesRunning();
+ QString OS_updateLog();
+ bool OS_updatesFinished();
+ QString OS_updateResults();
+ void OS_startUpdates();
+ bool OS_updateOnlyOnReboot();
+ bool OS_updateCausesReboot();
+ QDateTime OS_lastUpdate();
+ QString OS_lastUpdateResults();
+ // = System Power =
+ bool OS_canReboot();
+ void OS_startReboot();
+ bool OS_canShutdown();
+ void OS_startShutdown();
+ bool OS_canSuspend();
+ void OS_startSuspend();
+ // = Screen Brightness =
+ bool OS_brightnessSupported();
+ int OS_brightness();
+ bool OS_setBrightness(int);
+ // = System Status Monitoring
+ bool OS_cpuSupported();
+ QList<int> OS_cpuPercentage();
+ QStringList OS_cpuTemperatures();
+ bool OS_memorySupported();
+ int OS_memoryUsedPercentage();
+ QString OS_memoryTotal();
+ QStringList OS_diskIO();
+ bool OS_diskSupported();
+ int OS_fileSystemPercentage(QString dir);
+ QString OS_fileSystemCapacity(QString dir);
+
private slots:
// ================
// SEMI-VIRTUAL FUNCTIONS - NEED TO BE DEFINED IN THE OS-SPECIFIC FILES
// ================
+
//FileSystemWatcher slots
void watcherFileChanged(QString);
void watcherDirChanged(QString);
@@ -132,16 +223,20 @@ private slots:
void iodeviceReadyRead();
void iodeviceAboutToClose();
//NetworkAccessManager slots
- void netAccessChanged(QNetworkAccessManager::NetworkAccessibility);
void netRequestFinished(QNetworkReply*);
void netSslErrors(QNetworkReply*, const QList<QSslError>&);
//Timer slots
- void timerUpdate();
+ void NetworkTimerUpdate();
+ void BatteryTimerUpdate();
+ void UpdateTimerUpdate();
+ void BrightnessTimerUpdate();
+ void VolumeTimerUpdate();
+ void CpuTimerUpdate();
+ void MemTimerUpdate();
+ void DiskTimerUpdate();
signals:
- void batteryChargeChanged();
- void batteryChargingChanged();
- void batterySecondsLeftChanged();
+ void batteryChanged();
void volumeChanged();
void networkStatusChanged();
void mediaShortcutsChanged();
@@ -149,9 +244,14 @@ signals:
void powerAvailableChanged();
void brightnessChanged();
+ //Internal alert signals
+ void BatteryFullAlert();
+ void BatteryEmptyAlert();
+
private:
//Internal persistant data storage, OS-specific usage implementation
QHash< QString, QVariant> INFO;
+ bool _started;
// ============
// Internal possibilities for watching the system (OS-Specific usage/implementation)
@@ -163,28 +263,52 @@ private:
//Network Access Manager (check network connectivity, etc)
QNetworkAccessManager *netman;
//Timer for regular probes/updates
- QTimer *timer;
+ QTimer *networkTimer, *batteryTimer, *updateTimer, *brightnessTimer, *volumeTimer, *cpuTimer, *memTimer, *diskTimer;
// Internal implifications for connecting the various watcher objects to their respective slots
// (OS-agnostic - defined in the "OSInterface_private.cpp" file)
void connectWatcher(); //setup the internal connections *only*
void connectIodevice(); //setup the internal connections *only*
void connectNetman(); //setup the internal connections *only*
- void connectTimer(); //setup the internal connections *only*
+
+ //Internal simplification routines
+ bool verifyAppOrBin(QString chk);
+ QString runProcess(int &retcode, QString command, QStringList arguments, QString workdir = "", QStringList env = QStringList());
+ int runCmd(QString command, QStringList args = QStringList());
+ QStringList getCmdOutput(QString command, QStringList args = QStringList());
+ bool findInDirectory(QString file, QString dirpath, bool recursive=true);
+ QString readFile(QString path);
// External Media Management (if system uses *.desktop shortcuts only)
void setupMediaWatcher();
bool handleMediaDirChange(QString dir); //returns true if directory was handled
QStringList autoHandledMediaFiles();
- // Qt-based NetworkAccessManager usage
- void setupNetworkManager();
+ // Timer-based setups
+ void setupNetworkManager(int update_ms, int delay_ms);
+ void setupBatteryMonitor(int update_ms, int delay_ms);
+ void setupUpdateMonitor(int update_ms, int delay_ms);
+ void setupBrightnessMonitor(int update_ms, int delay_ms);
+ void setupVolumeMonitor(int update_ms, int delay_ms);
+ void setupCpuMonitor(int update_ms, int delay_ms);
+ void setupMemoryMonitor(int update_ms, int delay_ms);
+ void setupDiskMonitor(int update_ms, int delay_ms);
+
+ // Timer-based monitor update routines (NOTE: these are all run in a separate thread!!)
+ void syncNetworkInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncBatteryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncUpdateInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncBrightnessInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncVolumeInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncCpuInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncMemoryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncDiskInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
public:
OSInterface(QObject *parent = 0);
~OSInterface();
static OSInterface* instance(); //Get the currently-active instance of this class (or make a new one)
-
+ static void RegisterType(); //Register this object for QML access
};
#endif
diff --git a/src-qt5/src-cpp/framework-OSInterface.pri b/src-qt5/src-cpp/framework-OSInterface.pri
index be705e44..3a456382 100644
--- a/src-qt5/src-cpp/framework-OSInterface.pri
+++ b/src-qt5/src-cpp/framework-OSInterface.pri
@@ -1,9 +1,18 @@
-QT *= core network
+QT *= core network quick concurrent
+
+#include(../core/libLumina/LUtils.pri)
+#include(../core/libLumina/LuminaXDG.pri)
HEADERS *= $${PWD}/framework-OSInterface.h
SOURCES *= $${PWD}/framework-OSInterface_private.cpp
-_os=template
-SOURCES *= $${PWD}/framework-OSInterface-$${_os}.cpp
+#Load the proper OS *.cpp file
+exists($${PWD}/framework-OSInterface-$${LINUX_DISTRO}.cpp){
+ SOURCES *= $${PWD}/framework-OSInterface-$${LINUX_DISTRO}.cpp
+}else:exists($${PWD}/framework-OSInterface-$${OS}.cpp){
+ SOURCES *= $${PWD}/framework-OSInterface-$${OS}.cpp
+}else{
+ SOURCES *= $${PWD}/framework-OSInterface-template.cpp
+}
INCLUDEPATH *= $${PWD}
diff --git a/src-qt5/src-cpp/framework-OSInterface_private.cpp b/src-qt5/src-cpp/framework-OSInterface_private.cpp
index d15d9be8..15ee6f8e 100644
--- a/src-qt5/src-cpp/framework-OSInterface_private.cpp
+++ b/src-qt5/src-cpp/framework-OSInterface_private.cpp
@@ -7,9 +7,9 @@
// Internal, OS-agnostic functionality for managing the object itself
//===========================================
#include <framework-OSInterface.h>
-#include <QFile>
-#include <QDir>
-#include <QVariant>
+#include <QtConcurrent>
+
+#include <QQmlEngine>
OSInterface::OSInterface(QObject *parent) : QObject(parent){
watcher = 0;
@@ -40,6 +40,40 @@ OSInterface* OSInterface::instance(){
return m_os_object;
}
+void OSInterface::RegisterType(){
+ static bool done = false;
+ if(done){ return; }
+ done=true;
+ qmlRegisterType<OSInterface>("Lumina.Backend.OSInterface", 2, 0, "OSInterface");
+}
+
+//Start/stop interface systems
+void OSInterface::start(){
+ if(!mediaDirectories().isEmpty()){ setupMediaWatcher(); }//will create/connect the filesystem watcher automatically
+ setupNetworkManager(60000, 1); //will create/connect the network monitor automatically
+ if(batteryAvailable()){ setupBatteryMonitor(30000, 1); } //30 second updates, 1 ms init delay
+ if(brightnessSupported()){ setupBrightnessMonitor(60000, 1); } //1 minute updates, 1 ms init delay
+ if(volumeSupported()){ setupVolumeMonitor(60000, 2); } //1 minute updates, 2 ms init delay
+ if(updatesSupported()){ setupUpdateMonitor(12*60*60*1000, 5*60*1000); } //12-hour updates, 5 minute delay
+ if(cpuSupported()){ setupCpuMonitor(2000, 20); } //2 second updates, 20 ms init delay
+ if(memorySupported()){ setupMemoryMonitor(2000, 21); } //2 second updates, 21 ms init delay
+ if(diskSupported()){ setupDiskMonitor(60000, 25); } //1 minute updates, 25 ms init delay
+}
+
+void OSInterface::stop(){
+ if(watcher!=0){ watcher->deleteLater(); watcher=0; }
+ if(batteryTimer!=0){ batteryTimer->stop(); disconnect(batteryTimer); }
+ if(brightnessTimer!=0){ brightnessTimer->stop(); disconnect(brightnessTimer); }
+ if(volumeTimer!=0){ volumeTimer->stop(); disconnect(volumeTimer); }
+ if(updateTimer!=0){ updateTimer->stop(); disconnect(updateTimer); }
+ if(cpuTimer!=0){ cpuTimer->stop(); disconnect(cpuTimer); }
+ if(memTimer!=0){ memTimer->stop(); disconnect(memTimer); }
+ if(diskTimer!=0){ diskTimer->stop(); disconnect(diskTimer); }
+ if(netman!=0){ disconnect(netman); netman->deleteLater(); netman = 0; }
+}
+
+bool OSInterface::isRunning(){ return _started; } //status of the object - whether it has been started yet
+
void OSInterface::connectWatcher(){
if(watcher==0){ return; }
connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(watcherFileChanged(QString)) );
@@ -53,16 +87,119 @@ void OSInterface::connectIodevice(){
void OSInterface::connectNetman(){
if(netman==0){ return; }
- connect(netman, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(netAccessChanged(QNetworkAccessManager::NetworkAccessibility)) );
+ connect(netman, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(NetworkTimerUpdate()) );
connect(netman, SIGNAL(finished(QNetworkReply*)), this, SLOT(netRequestFinished(QNetworkReply*)) );
connect(netman, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(netSslErrors(QNetworkReply*, const QList<QSslError>&)) );
}
-void OSInterface::connectTimer(){
- if(timer==0){ return; }
- connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate()) );
+bool OSInterface::verifyAppOrBin(QString chk){
+ bool valid = !chk.isEmpty();
+ if(chk.contains(" ")){ chk = chk.section(" ",0,0); }
+ if(valid && chk.endsWith(".desktop")){
+ if(chk.startsWith("/")){ return QFile::exists(chk); }
+ valid = false;
+ QStringList paths;
+ paths << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":");
+ for(int i=0; i<paths.length() && !valid; i++){
+ if(QFile::exists(paths[i]+"/applications")){ valid = findInDirectory(chk, paths[i]+"/applications", true); }
+ }
+ }else if(valid){
+ //Find the absolute path for this binary
+ if(!chk.startsWith("/")){
+ QStringList paths = QString(getenv("PATH")).split(":");
+ for(int i=0; i<paths.length(); i++){
+ if(QFile::exists(paths[i]+"/"+chk)){ chk = paths[i]+"/"+chk; break; }
+ }
+ if(!chk.startsWith("/")){ return false; } //could not find the file
+ }else if(!QFile::exists(chk)){
+ return false; //file does not exist
+ }
+ //Make sure it is executable by the user
+ valid = QFileInfo(chk).isExecutable();
+ }
+ return valid;
}
+QString OSInterface::runProcess(int &retcode, QString command, QStringList arguments, QString workdir, QStringList env){
+ QProcess proc;
+ proc.setProcessChannelMode(QProcess::MergedChannels); //need output
+ //First setup the process environment as necessary
+ QProcessEnvironment PE = QProcessEnvironment::systemEnvironment();
+ if(!env.isEmpty()){
+ for(int i=0; i<env.length(); i++){
+ if(!env[i].contains("=")){ continue; }
+ PE.insert(env[i].section("=",0,0), env[i].section("=",1,100));
+ }
+ }
+ proc.setProcessEnvironment(PE);
+ //if a working directory is specified, check it and use it
+ if(!workdir.isEmpty()){
+ proc.setWorkingDirectory(workdir);
+ }
+ //Now run the command (with any optional arguments)
+ if(arguments.isEmpty()){ proc.start(command); }
+ else{ proc.start(command, arguments); }
+ //Wait for the process to finish (but don't block the event loop)
+ for(int i=0; i<10 && !proc.waitForFinished(500); i++){ //maximum of 5 seconds for command to finish
+ if(proc.state() == QProcess::NotRunning){ break; } //somehow missed the finished signal - go ahead and stop now
+ }
+ if(proc.state() != QProcess::NotRunning){ proc.terminate(); } //just in case - make sure to kill off the process
+ QString info = proc.readAllStandardOutput();
+ retcode = proc.exitCode(); //return success/failure
+ return info;
+}
+
+int OSInterface::runCmd(QString command, QStringList args){
+ int retcode;
+ runProcess(retcode, command, args);
+ return retcode;
+}
+
+QStringList OSInterface::getCmdOutput(QString command, QStringList args){
+ int retcode;
+ return runProcess(retcode, command, args).split("\n");
+}
+
+bool OSInterface::findInDirectory(QString file, QString dirpath, bool recursive){
+ bool found = QFile::exists(dirpath+"/"+file);
+ if(!found && recursive){
+ QDir dir(dirpath);
+ QStringList dirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
+ for(int i=0; i<dirs.length() && !found; i++){ found = findInDirectory(file, dir.absoluteFilePath(dirs[i]), recursive); }
+ }
+ return found;
+}
+
+QString OSInterface::readFile(QString path){
+ QFile file(path);
+ QString info;
+ if(file.open(QIODevice::ReadOnly)){
+ QTextStream out(&file);
+ info = out.readAll();
+ file.close();
+ }
+ return info;
+}
+
+// ===========================
+// OS SPECIFIC EXISTANCE CHECKS
+// ===========================
+bool OSInterface::hasControlPanel(){
+ return verifyAppOrBin(controlPanelShortcut());
+}
+
+bool OSInterface::hasAudioMixer(){
+ return verifyAppOrBin(audioMixerShortcut());
+}
+
+bool OSInterface::hasAppStore(){
+ return verifyAppOrBin(appStoreShortcut());
+}
+
+// ========================
+// MEDIA DIRECTORIES
+// ========================
+
// External Media Management (if system uses *.desktop shortcuts)
void OSInterface::setupMediaWatcher(){
//Create/connect the watcher if needed
@@ -99,12 +236,460 @@ QStringList OSInterface::autoHandledMediaFiles(){
return files;
}
+// =============================
+// NETWORK INTERFACE FUNCTIONS
+// =============================
// Qt-based NetworkAccessManager usage
-void OSInterface::setupNetworkManager(){
+void OSInterface::setupNetworkManager(int update_ms, int delay_ms){
if(netman==0){
netman = new QNetworkAccessManager(this);
connectNetman();
}
- //Load the initial state of the network accessibility
- netAccessChanged(netman->networkAccessible());
+ networkTimer = new QTimer(this);
+ networkTimer->setSingleShot(true);
+ networkTimer->setInterval(update_ms);
+ connect(networkTimer, SIGNAL(timeout()), this, SLOT(NetworkTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(NetworkTimerUpdate()) );
+}
+
+bool OSInterface::networkAvailable(){
+ if(INFO.contains("netaccess/available")){ return INFO.value("netaccess/available").toBool(); }
+ return false;
+}
+
+QString OSInterface::networkType(){
+ if(INFO.contains("netaccess/type")){ return INFO.value("netaccess/type").toString(); } //"wifi", "wired", or "cell"
+ return "";
+}
+
+float OSInterface::networkStrength(){
+ if(INFO.contains("netaccess/strength")){ return INFO.value("netaccess/strength").toFloat(); } //percentage
+ return -1;
+}
+
+QString OSInterface::networkIcon(){
+ if(INFO.contains("netaccess/icon")){ return INFO.value("netaccess/icon").toString(); }
+ return "";
+}
+
+QString OSInterface::networkHostname(){
+ return QHostInfo::localHostName();
+}
+
+QStringList OSInterface::networkAddress(){
+ QString addr;
+ if(INFO.contains("netaccess/address")){ addr = INFO.value("netaccess/address").toString(); }
+ return addr.split(", ");
+}
+
+bool OSInterface::hasNetworkManager(){
+ return verifyAppOrBin(networkManagerUtility());
+}
+
+QString OSInterface::networkStatus(){
+ QString stat = "<b>%1</b><br>%2<br>%3";
+ return stat.arg(networkHostname(), networkType(), networkAddress().join("<br>"));
+}
+
+//NetworkAccessManager slots
+void OSInterface::syncNetworkInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+ //qDebug() << "[DEBUG] Got Net Access Changed";
+ hash->insert("netaccess/available", netman->networkAccessible()== QNetworkAccessManager::Accessible);
+ //Update all the other network status info at the same time
+ QNetworkConfiguration active;
+ QList<QNetworkConfiguration> netconfigL = netman->configuration().children();
+ for(int i=0; i<netconfigL.length(); i++){
+ if(!netconfigL[i].state().testFlag(QNetworkConfiguration::Discovered) ){ continue; } //skip this interface
+ QList<QNetworkAddressEntry> addressList = QNetworkInterface::interfaceFromName(netconfigL[i].name()).addressEntries();
+ //NOTE: There are often 2 addresses, IPv4 and IPv6
+ bool ok = false;
+ for(int j=0; j<addressList.length() && !ok; j++){
+ if( addressList[j].ip().isLoopback() ){ continue; }
+ addressList[j].ip().toIPv4Address(&ok);
+ }
+ if(ok){ active = netconfigL[i]; break; } //found a good one with a valid IPv4
+ //else if(!active.isValid()){
+ }
+ if(!active.isValid()){ active = netman->activeConfiguration(); } //use the default Qt-detected interface
+ //Type of connection
+ QString type;
+ switch(active.bearerTypeFamily()){
+ case QNetworkConfiguration::BearerEthernet: type="wired"; break;
+ case QNetworkConfiguration::BearerWLAN: type="wifi"; break;
+ case QNetworkConfiguration::Bearer2G: type="cell-2G"; break;
+ case QNetworkConfiguration::Bearer3G: type="cell-3G"; break;
+ case QNetworkConfiguration::Bearer4G: type="cell-4G"; break;
+ default: type=OS_networkTypeFromDeviceName(active.name()); //could not be auto-determined - run the OS-specific routine
+ }
+ hash->insert("netaccess/type", type);
+ float strength = 100;
+ if(type!="wired"){ strength = OS_networkStrengthFromDeviceName(active.name()); }
+ hash->insert("netaccess/strength", strength);
+
+ //qDebug() << "Detected Device Status:" << active.identifier() << type << stat;
+ QNetworkInterface iface = QNetworkInterface::interfaceFromName(active.name());
+ //qDebug() << " - Configuration: Name:" << active.name() << active.bearerTypeName() << active.identifier();
+ //qDebug() << " - Interface: MAC Address:" << iface.hardwareAddress() << "Name:" << iface.name() << iface.humanReadableName() << iface.isValid();
+ QList<QNetworkAddressEntry> addressList = iface.addressEntries();
+ QStringList address;
+ //NOTE: There are often 2 addresses, IPv4 and IPv6
+ for(int i=0; i<addressList.length(); i++){
+ address << addressList[i].ip().toString();
+ }
+ //qDebug() << " - IP Address:" << address;
+ //qDebug() << " - Hostname:" << networkHostname();
+ hash->insert("netaccess/address", address.join(", "));
+
+ //Figure out the icon used for this type/strnegth
+ QString icon;
+ if(type.startsWith("cell")){
+ if(address.isEmpty()){ icon = "network-cell-off"; }
+ else if(strength>80){ icon = "network-cell-connected-100"; }
+ else if(strength>60){ icon = "network-cell-connected-75"; }
+ else if(strength>40){ icon = "network-cell-connected-50"; }
+ else if(strength>10){ icon = "network-cell-connected-25"; }
+ else if(strength >=0){ icon = "network-cell-connected-00"; }
+ else{ icon = "network-cell"; } //unknown strength - just use generic icon so we at least get off/on visibility
+ }else if(type=="wifi"){
+ if(address.isEmpty()){ icon = "network-wireless-off"; }
+ else if(strength>80){ icon = "network-wireless-100"; }
+ else if(strength>60){ icon = "network-wireless-75"; }
+ else if(strength>40){ icon = "network-wireless-50"; }
+ else if(strength>10){ icon = "network-wireless-25"; }
+ else if(strength >=0){ icon = "network-wireless-00"; }
+ else{ icon = "network-wireless"; } //unknown strength - just use generic icon so we at least get off/on visibility
+ }else if(type=="wired"){
+ if(strength==100 && !address.isEmpty()){ icon = "network-wired-connected"; }
+ else if(strength==100){ icon = "network-wired-pending"; }
+ else{ icon = "network-wired-disconnected"; }
+ }else{
+ icon = "network-workgroup"; //failover to a generic "network" icon
+ }
+ hash->insert("netaccess/icon",icon);
+ //qDebug() << "[DEBUG] Emit NetworkStatusChanged";
+ os->emit networkStatusChanged();
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+
+// ========================
+// TIMER-BASED MONITORS
+// ========================
+//Timer slots
+
+void OSInterface::NetworkTimerUpdate(){
+ if(networkTimer->isActive()){ networkTimer->stop(); } //just in case this was manually triggered
+ QtConcurrent::run(this, &OSInterface::syncNetworkInfo, this, &INFO, networkTimer);
+}
+
+void OSInterface::BatteryTimerUpdate(){
+ if(batteryTimer->isActive()){ batteryTimer->stop(); } //just in case this was manually triggered
+ QtConcurrent::run(this, &OSInterface::syncBatteryInfo, this, &INFO, batteryTimer);
+}
+
+void OSInterface::UpdateTimerUpdate(){
+ if(updateTimer->isActive()){ updateTimer->stop(); } //just in case this was manually triggered
+ QtConcurrent::run(this, &OSInterface::syncUpdateInfo, this, &INFO, updateTimer);
+}
+
+void OSInterface::BrightnessTimerUpdate(){
+ if(brightnessTimer->isActive()){ brightnessTimer->stop(); } //just in case this was manually triggered
+ QtConcurrent::run(this, &OSInterface::syncBrightnessInfo, this, &INFO, brightnessTimer);
+}
+
+void OSInterface::VolumeTimerUpdate(){
+ if(volumeTimer->isActive()){ volumeTimer->stop(); } //just in case this was manually triggered
+ QtConcurrent::run(this, &OSInterface::syncVolumeInfo, this, &INFO, volumeTimer);
+}
+
+void OSInterface::CpuTimerUpdate(){
+ if(cpuTimer->isActive()){ cpuTimer->stop(); } //just in case this was manually triggered
+ QtConcurrent::run(this, &OSInterface::syncCpuInfo, this, &INFO, cpuTimer);
+}
+
+void OSInterface::MemTimerUpdate(){
+ if(memTimer->isActive()){ memTimer->stop(); } //just in case this was manually triggered
+ QtConcurrent::run(this, &OSInterface::syncMemoryInfo, this, &INFO, memTimer);
+}
+
+void OSInterface::DiskTimerUpdate(){
+ if(diskTimer->isActive()){ diskTimer->stop(); } //just in case this was manually triggered
+ QtConcurrent::run(this, &OSInterface::syncDiskInfo, this, &INFO, diskTimer);
+}
+
+// Timer Setup functions
+void OSInterface::setupBatteryMonitor(int update_ms, int delay_ms){
+ batteryTimer = new QTimer(this);
+ batteryTimer->setSingleShot(true);
+ batteryTimer->setInterval(update_ms);
+ connect(batteryTimer, SIGNAL(timeout()), this, SLOT(BatteryTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(BatteryTimerUpdate()) );
+}
+void OSInterface::setupUpdateMonitor(int update_ms, int delay_ms){
+ updateTimer = new QTimer(this);
+ updateTimer->setSingleShot(true);
+ updateTimer->setInterval(update_ms);
+ connect(updateTimer, SIGNAL(timeout()), this, SLOT(UpdateTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(UpdateTimerUpdate()) );
+}
+void OSInterface::setupBrightnessMonitor(int update_ms, int delay_ms){
+ brightnessTimer = new QTimer(this);
+ brightnessTimer->setSingleShot(true);
+ brightnessTimer->setInterval(update_ms);
+ connect(brightnessTimer, SIGNAL(timeout()), this, SLOT(BrightnessTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(BrightnessTimerUpdate()) );
+}
+void OSInterface::setupVolumeMonitor(int update_ms, int delay_ms){
+ volumeTimer = new QTimer(this);
+ volumeTimer->setSingleShot(true);
+ volumeTimer->setInterval(update_ms);
+ connect(volumeTimer, SIGNAL(timeout()), this, SLOT(VolumeTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(VolumeTimerUpdate()) );
+}
+void OSInterface::setupCpuMonitor(int update_ms, int delay_ms){
+ cpuTimer = new QTimer(this);
+ cpuTimer->setSingleShot(true);
+ cpuTimer->setInterval(update_ms);
+ connect(cpuTimer, SIGNAL(timeout()), this, SLOT(CpuTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(CpuTimerUpdate()) );
+}
+void OSInterface::setupMemoryMonitor(int update_ms, int delay_ms){
+ memTimer = new QTimer(this);
+ memTimer->setSingleShot(true);
+ memTimer->setInterval(update_ms);
+ connect(memTimer, SIGNAL(timeout()), this, SLOT(MemTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(MemTimerUpdate()) );
+}
+void OSInterface::setupDiskMonitor(int update_ms, int delay_ms){
+ diskTimer = new QTimer(this);
+ diskTimer->setSingleShot(true);
+ diskTimer->setInterval(update_ms);
+ connect(diskTimer, SIGNAL(timeout()), this, SLOT(DiskTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(DiskTimerUpdate()) );
+}
+
+// Timer-based monitor update routines (NOTE: these are all run in a separate thread!!)
+void OSInterface::syncBatteryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+ float charge = OS_batteryCharge();
+ bool charging = OS_batteryCharging();
+ double secs = OS_batterySecondsLeft();
+ //Check for any alert generations
+ if(charging && hash->value("battery/percent",100).toFloat() <= 99 && charge>99){ os->emit BatteryFullAlert(); }
+ else if(!charging && hash->value("battery/percent", 50).toFloat()>10 && charge<10){ os->emit BatteryEmptyAlert(); }
+
+ hash->insert("battery/percent",charge);
+ hash->insert("battery/charging",charging);
+ //Convert the seconds to human-readable
+ QString time;
+ if(secs>3600){
+ time = QString::number( qRound(secs/360.0)/10.0 )+" h";
+ }else if(secs>60){
+ time = QString::number( qRound(secs/6.0)/10.0 )+" m";
+ }else if(secs>0){
+ time = QString::number(secs)+" s";
+ }
+ hash->insert("battery/time", time);
+ //Determine the icon which should be used for this status
+ QString icon;
+ if(charging){
+ if(charge>=99){ icon="battery-charging"; }
+ else if(charge>80){ icon="battery-charging-80"; }
+ else if(charge >60){ icon="battery-charging-60"; }
+ else if(charge >30){ icon="battery-charging-40"; }
+ else if(charge >0){ icon="battery-charging-20"; }
+ else{ icon="battery-unknown"; }
+ }else{
+ if(charge>90){ icon="battery"; }
+ else if(charge>80){ icon="battery-80"; }
+ else if(charge >60){ icon="battery-60"; }
+ else if(charge >30){ icon="battery-40"; }
+ else if(charge >10){ icon="battery-20"; }
+ else if(charge >0){ icon="battery-alert"; }
+ else{ icon="battery-unknown"; }
+ }
+ hash->insert("battery/icon",icon);
+ //Now emit the change signal and restart the timer
+ os->emit batteryChanged();
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncUpdateInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+ //Get the current status
+ QString status, icon;
+ if(OS_updatesRunning()){
+ status="running"; icon="sync";
+ }else if(OS_updatesFinished()){
+ status="finished"; icon="security-high";
+ }else if(OS_updatesAvailable()){
+ status="available"; icon="security-medium";
+ }
+ //Save the current info into the hash (if different)
+ if(status != updateStatus()){
+ hash->insert("updates/status", status);
+ hash->insert("updates/icon", icon);
+ os->emit updateStatusChanged();
+ }
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncBrightnessInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncVolumeInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+ int oldvol = volume();
+ int newvol = OS_volume();
+ if(oldvol!=newvol && newvol>=0){
+ hash->insert("volume/current",newvol);
+ QString icon;
+ if(newvol>66){ icon = "audio-volume-high"; }
+ else if(newvol>33){ icon = "audio-volume-medium"; }
+ else if(newvol>0){ icon = "audio-volume-low"; }
+ else{ icon = "audio-volume-muted"; }
+ hash->insert("volume/icon",icon);
+ os->emit volumeChanged();
+ }
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncCpuInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncMemoryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncDiskInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+// = Battery =
+bool OSInterface::batteryAvailable(){ return OS_batteryAvailable(); }
+float OSInterface::batteryCharge(){
+ if(INFO.contains("battery/percent")){ return INFO.value("battery/percent").toFloat(); }
+ return -1;
}
+bool OSInterface::batteryCharging(){
+ if(INFO.contains("battery/charging")){ return INFO.value("battery/charging").toBool(); }
+ return false;
+}
+QString OSInterface::batteryRemaining(){
+ if(INFO.contains("battery/time")){ return INFO.value("battery/time").toString(); }
+ return "";
+}
+QString OSInterface::batteryIcon(){
+ if(INFO.contains("battery/icon")){ return INFO.value("battery/icon").toString(); }
+ return "";
+}
+
+QString OSInterface::batteryStatus(){
+ QString text = QString::number(batteryCharge())+"%";
+ if(!batteryCharging()){
+ QString time = batteryRemaining();
+ if(!time.isEmpty()){
+ text.append(" ("+time+")");
+ }
+ }
+ return text;
+}
+
+// = Volume =
+bool OSInterface::volumeSupported(){ return OS_volumeSupported(); }
+int OSInterface::volume(){
+ if(INFO.contains("volume/current")){ return INFO.value("volume/current").toInt(); }
+ return 0;
+}
+
+void OSInterface::setVolume(int vol){
+ OS_setVolume(vol);
+ VolumeTimerUpdate(); //update the internal cache
+}
+
+QString OSInterface::volumeIcon(){
+ if(INFO.contains("volume/icon")){ return INFO.value("volume/icon").toString(); }
+ return "";
+}
+
+// = Media =
+QStringList OSInterface::mediaDirectories(){ return OS_mediaDirectories(); }
+QStringList OSInterface::mediaShortcuts(){ return autoHandledMediaFiles(); } //List of currently-available XDG shortcut file paths
+
+// = Updates =
+bool OSInterface::updatesSupported(){ return OS_updatesSupported(); }
+QString OSInterface::updateStatus(){
+ if(INFO.contains("updates/status")){ return INFO.value("updates/status").toString(); }
+ return "";
+}
+bool OSInterface::updateInfoAvailable(){
+ return !updateStatus().isEmpty();
+}
+
+QString OSInterface::updateIcon(){
+ if(INFO.contains("updates/icon")){ return INFO.value("updates/icon").toString(); }
+ return "";
+}
+
+QString OSInterface::updateStatusInfo(){
+ QString status = updateStatus();
+ if(status=="available"){ return updateDetails(); }
+ else if(status=="running"){ return updateLog(); }
+ else if(status=="finished"){ return updateResults(); }
+ return "";
+}
+
+QString OSInterface::updateDetails(){
+ return OS_updateDetails(); //don't cache these types of logs - too large
+}
+
+QString OSInterface::updateLog(){
+ return OS_updateLog(); //don't cache these types of logs - too large and change too often
+}
+
+QString OSInterface::updateResults(){
+ return OS_updateResults(); //don't cache these types of logs - too large
+}
+
+void OSInterface::startUpdates(){ OS_startUpdates(); }
+bool OSInterface::updateOnlyOnReboot(){ return OS_updateOnlyOnReboot(); }
+bool OSInterface::updateCausesReboot(){ return OS_updateCausesReboot(); }
+
+QDateTime OSInterface::lastUpdate(){ return OS_lastUpdate(); }
+QString OSInterface::lastUpdateResults(){ return OS_lastUpdateResults(); }
+
+// = System Power =
+bool OSInterface::canReboot(){ return OS_canReboot(); }
+void OSInterface::startReboot(){ OS_startReboot(); }
+bool OSInterface::canShutdown(){ return OS_canShutdown(); }
+void OSInterface::startShutdown(){ OS_startShutdown(); }
+bool OSInterface::canSuspend(){ return OS_canSuspend(); }
+void OSInterface::startSuspend(){ OS_startSuspend(); }
+
+// = Screen Brightness =
+bool OSInterface::brightnessSupported(){ return OS_brightnessSupported(); }
+int OSInterface::brightness(){
+ if(INFO.contains("brightness/percent")){ return INFO.value("brightness/percent").toInt(); }
+ return 100;
+}
+void OSInterface::setBrightness(int percent){
+ OS_setBrightness(percent);
+ BrightnessTimerUpdate(); //update internal cache ASAP
+}
+
+// = System Status Monitoring
+bool OSInterface::cpuSupported(){ return OS_cpuSupported(); }
+QList<int> OSInterface::cpuPercentage(){ return QList<int>(); } // (one per CPU) percentage: 0-100 with empty list for errors
+QStringList OSInterface::cpuTemperatures(){ return QStringList(); } // (one per CPU) Temperature of CPU ("50C" for example)
+
+bool OSInterface::memorySupported(){ return false; }
+int OSInterface::memoryUsedPercentage(){ return -1; } //percentage: 0-100 with -1 for errors
+QString OSInterface::memoryTotal(){ return QString(); } //human-readable form - does not tend to change within a session
+QStringList OSInterface::diskIO(){ return QStringList(); } //Returns list of current read/write stats for each device
+
+bool OSInterface::diskSupported(){ return false; }
+int OSInterface::fileSystemPercentage(QString dir){ return -1; } //percentage of capacity used: 0-100 with -1 for errors
+QString OSInterface::fileSystemCapacity(QString dir){ return QString(); } //human-readable form - total capacity
diff --git a/src-qt5/src-cpp/plugins-base.h b/src-qt5/src-cpp/plugins-base.h
index 26b0eacc..eb54e40d 100644
--- a/src-qt5/src-cpp/plugins-base.h
+++ b/src-qt5/src-cpp/plugins-base.h
@@ -35,12 +35,12 @@ public:
virtual void loadFile(QString path);
bool isLoaded() { return !data.isEmpty(); };
- bool containsDefault(QString obj) { return data.value(obj).toObject().contains("default"); }
+ bool containsDefault(QString obj) { return data.value(obj).toObject().contains("default"); }
/**
* Check if the plugin is valid as long as the JSON is not empty,
* it contains at least a "name", "qml", and "description" object,
- * and the "name" and "description" objects contain a "default" key.
+ * and the "name" and "description" objects contain a "default" key.
**/
virtual bool isValid() = 0;
@@ -48,7 +48,7 @@ public:
virtual QUrl scriptURL();
QJsonObject data; //Hazardous to manually modify
- QString relDir;
+ QString relDir;
};
class PluginSystem{
diff --git a/src-qt5/src-cpp/plugins-desktop.cpp b/src-qt5/src-cpp/plugins-desktop.cpp
index fdbd676d..19c49942 100644
--- a/src-qt5/src-cpp/plugins-desktop.cpp
+++ b/src-qt5/src-cpp/plugins-desktop.cpp
@@ -6,15 +6,15 @@
//===========================================
#include "plugins-desktop.h"
+#include <LuminaXDG.h>
+
// ============
// DT PLUGIN
// ============
DTPlugin::DTPlugin(){
-
}
DTPlugin::~DTPlugin(){
-
}
bool DTPlugin::isValid(){
@@ -22,8 +22,10 @@ bool DTPlugin::isValid(){
bool ok = data.contains("name") && data.contains("qml") && data.contains("description");
ok &= containsDefault("name");
ok &= containsDefault("description");
+ ok &= containsDefault("data");
if(ok) {
QJsonObject tmp = data.value("qml").toObject();
+
QStringList mustexist;
QString exec = tmp.value("exec").toString();
if(exec.isEmpty() || !exec.endsWith(".qml")){ return false; }
@@ -38,3 +40,33 @@ bool DTPlugin::isValid(){
}
return ok;
}
+
+QSize DTPlugin::getSize(){
+ QString gridS = data.value("data").toObject().value("grid_size").toString();
+ QSize gridSize(0,0);
+ if(!gridS.isEmpty()) {
+ QStringList gridList = gridS.split("x");
+ if(gridList.size() == 2) {
+ int width = gridList[0].toInt();
+ int height = gridList[1].toInt();
+ if(width > 0 && height > 0)
+ gridSize = QSize(width, height);
+ }
+ }
+ return gridSize;
+}
+
+bool DTPlugin::supportsPanel(){
+ QString possibleS = data.value("data").toObject().value("panel_possible").toString().toLower();
+ bool panelPossible = false;
+ if(!possibleS.isEmpty() && (possibleS == "yes" || possibleS == "true")){
+ panelPossible = true;
+ }
+ return panelPossible;
+}
+
+QString DTPlugin::getIcon(){
+ QString iconS = data.value("data").toObject().value("plugin_icon").toString();
+ if(iconS.isEmpty()){ iconS = "preferences-plugin"; }
+ return iconS;
+}
diff --git a/src-qt5/src-cpp/plugins-desktop.h b/src-qt5/src-cpp/plugins-desktop.h
index ed576db1..260f9070 100644
--- a/src-qt5/src-cpp/plugins-desktop.h
+++ b/src-qt5/src-cpp/plugins-desktop.h
@@ -17,13 +17,19 @@
#include <QFile>
#include <QDir>
#include <QDebug>
+#include <QIcon>
class DTPlugin : public BasePlugin{
+
public:
DTPlugin();
~DTPlugin();
virtual bool isValid() Q_DECL_OVERRIDE;
+
+ QSize getSize();
+ bool supportsPanel();
+ QString getIcon();
};
#endif
diff --git a/src-qt5/src-cpp/tests/main.cpp b/src-qt5/src-cpp/tests/main.cpp
index 682c318a..215d1620 100644
--- a/src-qt5/src-cpp/tests/main.cpp
+++ b/src-qt5/src-cpp/tests/main.cpp
@@ -34,5 +34,8 @@ int main(int argc, char** argv){
timer->start();
int ret = A.exec();
qDebug() << " - Finished";
+ qDebug() << "Ending Status:";
+ qDebug() << "OS.networkAvailable:" << OS.networkAvailable();
+ qDebug() << " - " << OS.networkType() << OS.networkStrength() << OS.networkIcon() << OS.networkHostname() << OS.networkAddress();
return ret;
}
bgstack15