1 /***************************************************************************
2 *                                                                         *
3 *   This program is free software; you can redistribute it and/or modify  *
4 *   it under the terms of the GNU General Public License as published by  *
5 *   the Free Software Foundation; either version 3 of the License, or     *
6 *   (at your option) any later version.                                   *
7 *                                                                         *
8 ***************************************************************************/
9 
10 #pragma once
11 
12 #include <QApplication>
13 #include <QEvent>
14 #include <QTimer>
15 #include <QSessionManager>
16 #include "WulforSettings.h"
17 #include "MainWindow.h"
18 #include "qtsingleapp/qtsinglecoreapplication.h"
19 #include <objc/objc.h>
20 #include <objc/message.h>
21 
22 bool dockClickHandler(id self,SEL _cmd,...);
23 
24 class EiskaltEventFilter: public QObject{
25 Q_OBJECT
26 public:
EiskaltEventFilter()27     EiskaltEventFilter(): counter(0), has_activity(true) {
28         timer.setInterval(60000);
29 
30         connect(&timer, SIGNAL(timeout()), this, SLOT(tick()));
31 
32         timer.start();
33     }
34 
~EiskaltEventFilter()35     virtual ~EiskaltEventFilter() {}
36 
37 protected:
eventFilter(QObject * obj,QEvent * event)38     virtual bool eventFilter(QObject *obj, QEvent *event){
39         switch (event->type()){
40             case QEvent::MouseButtonPress:
41             case QEvent::MouseButtonRelease:
42             case QEvent::MouseButtonDblClick:
43             case QEvent::MouseMove:
44             case QEvent::KeyPress:
45             case QEvent::KeyRelease:
46             case QEvent::Wheel:
47             {
48                 has_activity = true;
49                 counter = 0;
50 
51                 break;
52             }
53             default:
54             {
55                 has_activity = false;
56 
57                 break;
58             }
59         }
60 
61         return QObject::eventFilter(obj, event);
62     }
63 
64 private Q_SLOTS:
tick()65     void tick(){
66         if (!has_activity)
67             ++counter;
68 
69         if (WBGET(WB_APP_AUTOAWAY_BY_TIMER)){
70             int mins = WIGET(WI_APP_AUTOAWAY_INTERVAL);
71 
72             if (!mins)
73                 return;
74 
75             int mins_done = (counter*timer.interval()/1000)/60;
76 
77             if (mins <= mins_done)
78                 dcpp::Util::setAway(true);
79         }
80         else if (has_activity && !dcpp::Util::getManualAway())
81             dcpp::Util::setAway(false);
82     }
83 
84 private:
85     QTimer timer;
86     int counter;
87     bool has_activity;
88 };
89 
90 class EiskaltApp: public QtSingleCoreApplication {
91 Q_OBJECT
92 public:
EiskaltApp(int & argc,char * argv[],const QString & uniqKey)93     EiskaltApp(int &argc, char *argv[], const QString& uniqKey): QtSingleCoreApplication(argc, argv, uniqKey)
94     {
95         installEventFilter(&ef);
96         installMacHandlers();
97     }
98 
commitData(QSessionManager & manager)99     void commitData(QSessionManager& manager){
100         if (MainWindow::getInstance()){
101             MainWindow::getInstance()->beginExit();
102             MainWindow::getInstance()->close();
103         }
104 
105         manager.release();
106     }
107 
saveState(QSessionManager &)108     void saveState(QSessionManager &){ /** Do nothing */ }
109 
110 private:
111     EiskaltEventFilter ef;
112 
installMacHandlers()113     void installMacHandlers(){
114         objc_object* cls = (objc_object*)objc_getClass("NSApplication");
115         SEL sharedApplication = sel_registerName("sharedApplication");
116         objc_object* appInst = objc_msgSend(cls, sharedApplication);
117 
118         if (appInst){
119             objc_object* delegate = objc_msgSend(appInst,  sel_registerName("delegate"));
120             objc_object* delClass = objc_msgSend(delegate, sel_registerName("class"));
121             const char* tst = class_getName(delClass->isa);
122             bool test = class_addMethod((objc_class*)delClass,
123                                         sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"),
124                                         (IMP)dockClickHandler,"B@:");
125             if (!test){
126                 // failed to register handler...
127             }
128         }
129     }
130 };
131