aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/lumina-desktop-unified/src-events/LShortcutEvents.cpp
blob: b09a1a5b47c3c8b7d51fbead9d034bd10accbe3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//===========================================
//  Lumina desktop source code
//  Copyright (c) 2017, Ken Moore
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "LShortcutEvents.h"
#include "global-objects.h"

// === PUBLIC ===
LShortcutEvents::LShortcutEvents(){
  WIN = 0;
  clearTimer = 0;
  evaluated = false;
}

LShortcutEvents::~LShortcutEvents(){

}

void LShortcutEvents::start(){
  if(clearTimer==0){
    clearTimer = new QTimer(this);
    clearTimer->setInterval(2000); //2 seconds
    clearTimer->setSingleShot(true);
    connect(clearTimer, SIGNAL(timeout()), this, SLOT(clearKeys()) );
  }
  //Now connect this object to the global EFILTER object signals
  connect(Lumina::EFILTER, SIGNAL(KeyPressed(WId, int)), this, SLOT(KeyPress(WId, int)) );
  connect(Lumina::EFILTER, SIGNAL(KeyReleased(WId, int)), this, SLOT(KeyRelease(WId, int)) );
  connect(Lumina::EFILTER, SIGNAL(MousePressed(WId, Lumina::MouseButton)), this, SLOT(MousePress(WId, Lumina::MouseButton)) );
  connect(Lumina::EFILTER, SIGNAL(MouseReleased(WId, Lumina::MouseButton)), this, SLOT(MouseRelease(WId, Lumina::MouseButton)) );
}

void LShortcutEvents::stop(){
  disconnect(Lumina::EFILTER, SIGNAL(KeyPressed(WId, int)), this, SLOT(KeyPress(WId, int)) );
  disconnect(Lumina::EFILTER, SIGNAL(KeyReleased(WId, int)), this, SLOT(KeyRelease(WId, int)) );
  disconnect(Lumina::EFILTER, SIGNAL(MousePressed(WId, Lumina::MouseButton)), this, SLOT(MousePress(WId, Lumina::MouseButton)) );
  disconnect(Lumina::EFILTER, SIGNAL(MouseReleased(WId, Lumina::MouseButton)), this, SLOT(MouseRelease(WId, Lumina::MouseButton)) );
  clearKeys();
}

// === PRIVATE ===
void LShortcutEvents::CheckKeySequence(WId win){
  //Get the keyboard modifiers
  QString shortcut = keylistToString();
 //Now see if there is a match for this shortcut
  //  "strict" actions (operate even if a non-desktop window is active/focused)
  QString action = Lumina::SETTINGS->value(DesktopSettings::Keys, "strict/"+shortcut, "").toString();
  qDebug() << "Strict Action:" << "strict/"+shortcut << action;
  if(action.isEmpty() && win==0){
    //"loose" actions (operating on the desktop or root window itself)
    action = Lumina::SETTINGS->value(DesktopSettings::Keys, "desktop/"+shortcut, "").toString();
    qDebug() << "Desktop Action:" << "desktop/"+shortcut << action;
  }
  if(!action.isEmpty()){
    //Found a valid action - go ahead and evaluate it
    evaluateShortcutAction(action);
  }
}

void LShortcutEvents::CheckMouseSequence(WId win, Lumina::MouseButton button, bool release){
  if(release && (button == Lumina::WheelUp || button == Lumina::WheelDown || button == Lumina::WheelLeft || button == Lumina::WheelRight)){ 
    return; //skip mouse release events for wheel actions (always come in pairs of press/release)
  }else if(keylist.isEmpty() || button == Lumina::NoButton){ return; } //Never overwrite mouse clicks themselves - just combinations with key presses
  //Get the keyboard modifiers
  QString shortcut = keylistToString();
  //Add the mouse button to the shortcut
  switch(button){
    case Lumina::LeftButton:
      shortcut.append("+LeftMouse");
      break;
    case Lumina::RightButton:
      shortcut.append("+RightMouse");
      break;
    case Lumina::MidButton:
      shortcut.append("+MiddleMouse");
      break;
    case Lumina::BackButton:
      shortcut.append("+BackMouse");
      break;
    case Lumina::ForwardButton:
      shortcut.append("+ForwardMouse");
      break;
    case Lumina::TaskButton:
      shortcut.append("+TaskMouse");
      break;
    case Lumina::WheelUp:
      shortcut.append("+WheelUp");
      break;
    case Lumina::WheelDown:
      shortcut.append("+WheelDown");
      break;
    case Lumina::WheelLeft:
      shortcut.append("+WheelLeft");
      break;
    case Lumina::WheelRight:
      shortcut.append("+WheelRight");
      break;
    default:
      shortcut.clear();
  }
  if(shortcut.isEmpty()){ return; }
  //Now see if there is a match for this shortcut
  //  "strict" actions (operate even if a non-desktop window is active/focused)
  QString action = Lumina::SETTINGS->value(DesktopSettings::Keys, "strict/"+shortcut, "").toString();
  if(action.isEmpty() && win==0){
    //"loose" actions (operating on the desktop or root window itself)
    action = Lumina::SETTINGS->value(DesktopSettings::Keys, "desktop/"+shortcut, "").toString();
  }
  if(!action.isEmpty()){
    //Found a valid action - go ahead and evaluate it
    evaluateShortcutAction(action);
  }
}

QString LShortcutEvents::keylistToString(){
  QString shortcut;
  for(int i=0; i<keylist.length(); i++){
    if(i>0){ shortcut.append("+"); }
    shortcut.append( QString::number(keylist[i]) );
  }
  /*qDebug() << "KeyList to String:";
  qDebug() << "  keys:" << keylist;
  qDebug() << "  string:" << shortcut;*/
  return shortcut;
}

void LShortcutEvents::evaluateShortcutAction(QString action){
  qDebug() << "Found Shortcut Action:" << action;
  evaluated = true;
  if(action.startsWith("Exec=")){
    emit LaunchApplication(action.section("=",1,-1));
    return;
  }
  //Specific Internal actions
  action = action.toLower();
  //Power Options
  if(action=="logout"){ emit StartLogout(); }
  else if(action=="reboot"){ emit StartReboot(); }
  else if(action=="shutdown"){ emit StartShutdown(); }
  else if(action=="show_leave_options"){ emit OpenLeaveDialog(); }

}

// === PUBLIC SLOTS ===
void LShortcutEvents::KeyPress(WId window, int key){
  if(window!=WIN){ keylist.clear(); WIN = window; }
  if(!keylist.contains(key)){ 
    //Put it in the list in ascending order
    bool found = false;
    for(int i=0; i<keylist.length() && !found; i++){
      if(keylist[i]>key){ keylist.insert(i,key); found = true; }
    }
    if(!found){ keylist << key;  }
    evaluated = false;
  }
  //Evaluate the key sequence only when the first one is released
  clearTimer->start(); //will "restart" if already running 
}

void LShortcutEvents::KeyRelease(WId window, int key){
  if(window!=WIN){ keylist.clear(); return; }
  if(!evaluated){ CheckKeySequence(WIN); } //run this "before" removing the key from the list
  keylist.removeAll(key);
  clearTimer->start(); //will "restart" if already running 
}

void LShortcutEvents::MousePress(WId window, Lumina::MouseButton button){
  //We do not provide shortcuts for combinations of mouse buttons - just mouse+keyboard combinations
  CheckMouseSequence(window, button, false);
  clearTimer->start(); //will "restart" if already running 
}

void LShortcutEvents::MouseRelease(WId window, Lumina::MouseButton button){
  //We do not provide shortcuts for combinations of mouse buttons - just mouse+keyboard combinations
  CheckMouseSequence(window, button, true);
  clearTimer->start(); //will "restart" if already running 
}

void LShortcutEvents::clearKeys(){
  keylist.clear();
  WIN = 0;
  if(clearTimer!=0){ clearTimer->stop(); }
}
bgstack15