clear selections in all tabs when selection ownership is lost
[k8sterm.git] / src / x11evtmouse.c
blob722b586d249afaef96e9a7013a9b3e664acddb18
1 ////////////////////////////////////////////////////////////////////////////////
2 static int x2tab (int x) {
3 if (x >= 0 && x < xw.w && xw.tabheight > 0) {
4 x /= (xw.w/opt_tabcount)+firstVisibleTab;
5 return (x >= 0 && x < term_count) ? x : -1;
7 return -1;
11 static void msTabSwitch (XEvent *e) {
12 int tabn = x2tab(e->xbutton.x)+firstVisibleTab;
14 if (tabn >= 0 && tabn != termidx) switchToTerm(tabn, 1);
18 static void msTabScrollLeft (void) {
19 if (firstVisibleTab > 0) {
20 --firstVisibleTab;
21 updateTabBar = 1;
22 xdrawTabBar();
27 static void msTabScrollRight (void) {
28 int newidx = firstVisibleTab+1;
30 if (newidx > term_count-opt_tabcount) return;
31 firstVisibleTab = newidx;
32 updateTabBar = 1;
33 xdrawTabBar();
37 ////////////////////////////////////////////////////////////////////////////////
38 static void xdoMouseReport (K8Term *term, XEvent *e) {
39 int x = K8T_X2COL(e->xbutton.x);
40 int y = K8T_Y2ROW(term, e->xbutton.y);
41 int button = e->xbutton.button-Button1+K8T_MOUSE_BUTTON_LEFT;
42 int state, event;
44 if (e->xbutton.type == MotionNotify) event = K8T_MOUSE_EVENT_MOTION;
45 else if (e->xbutton.type == ButtonPress) event = K8T_MOUSE_EVENT_DOWN;
46 else if (e->xbutton.type == ButtonRelease) event = K8T_MOUSE_EVENT_UP;
47 else return;
49 state =
50 (e->xbutton.state&ShiftMask ? K8T_MOUSE_STATE_SHIFT : 0) |
51 (e->xbutton.state&Mod1Mask ? K8T_MOUSE_STATE_ALT : 0) |
52 (e->xbutton.state&ControlMask ? K8T_MOUSE_STATE_CTRL : 0) |
53 (e->xbutton.state&Mod4Mask ? K8T_MOUSE_STATE_WIN : 0);
55 k8t_mouseReport(term, x, y, event, button, state);
59 static void getButtonInfo (K8Term *term, XEvent *e, int *b, int *x, int *y) {
60 if (b != NULL) *b = e->xbutton.button;
61 if (x != NULL) *x = K8T_X2COL(e->xbutton.x);
62 if (y != NULL) *y = K8T_Y2ROW(term, e->xbutton.y);
63 term->sel.b.x = (term->sel.by < term->sel.ey ? term->sel.bx : term->sel.ex);
64 term->sel.b.y = K8T_MIN(term->sel.by, term->sel.ey);
65 term->sel.e.x = (term->sel.by < term->sel.ey ? term->sel.ex : term->sel.bx);
66 term->sel.e.y = K8T_MAX(term->sel.by, term->sel.ey);
70 static void xevtcbbpress (XEvent *e) {
71 if (curterm == NULL) return;
73 if (xw.tabheight > 0) {
74 if ((opt_tabposition == 0 && e->xbutton.y >= xw.h-xw.tabheight) ||
75 (opt_tabposition != 0 && e->xbutton.y < xw.tabheight)) {
76 switch (e->xbutton.button) {
77 case Button1: // left
78 msTabSwitch(e);
79 break;
80 case Button4: // wheel up
81 msTabScrollLeft();
82 break;
83 case Button5: // wheel down
84 msTabScrollRight();
85 break;
87 return;
90 // <shift|alt>+mouse: some cool shit
91 if ((e->xbutton.state&(ShiftMask|Mod1Mask)) != 0) {
92 switch (e->xbutton.button) {
93 case Button1: // left
94 if (curterm->sel.bx != -1) k8t_tmDirty(curterm, curterm->sel.b.y, curterm->sel.e.y);
95 curterm->sel.mode = 1;
96 curterm->sel.b.y = curterm->sel.e.y = curterm->row+1;
97 curterm->sel.ex = curterm->sel.bx = K8T_X2COL(e->xbutton.x);
98 curterm->sel.ey = curterm->sel.by = K8T_Y2ROW(curterm, e->xbutton.y);
99 //fprintf(stderr, "x=%d; y=%d\n", curterm->sel.bx, curterm->sel.by);
100 k8t_drawTerm(curterm, 1);
101 break;
103 case Button3: // middle
104 curterm->sel.bx = -1;
105 k8t_selCopy(curterm);
106 k8t_drawTerm(curterm, 1);
107 break;
109 case Button4: // wheel up
110 scrollHistory(curterm, 3);
111 break;
112 case Button5: // wheel down
113 scrollHistory(curterm, -3);
114 break;
116 return;
119 if (K8T_ISSET(curterm, K8T_MODE_MOUSE)) xdoMouseReport(curterm, e);
123 static void xevtcbbrelease (XEvent *e) {
124 if (curterm == NULL) return;
126 switch (opt_tabposition) {
127 case 0: // bottom
128 if (e->xbutton.y >= xw.h-xw.tabheight) return;
129 break;
130 case 1: // top
131 if (e->xbutton.y < xw.tabheight) return;
132 break;
135 if ((e->xbutton.state&ShiftMask) == 0 && !curterm->sel.mode) {
136 if (K8T_ISSET(curterm, K8T_MODE_MOUSE)) xdoMouseReport(curterm, e);
137 return;
140 if (e->xbutton.button == Button2) {
141 selpaste(curterm, XA_PRIMARY);
142 } else if (e->xbutton.button == Button1) {
143 curterm->sel.mode = 0;
144 getButtonInfo(curterm, e, NULL, &curterm->sel.ex, &curterm->sel.ey); // this sets sel.b and sel.e
146 if (curterm->sel.bx == curterm->sel.ex && curterm->sel.by == curterm->sel.ey) {
147 // single line, single char selection
148 K8TTimeMSec now;
150 k8t_tmDirtyMark(curterm, curterm->sel.ey, 2);
151 curterm->sel.bx = -1;
152 now = mclock_ticks();
153 if (now-curterm->sel.tclick2 <= opt_tripleclick_timeout) {
154 /* triple click on the line */
155 curterm->sel.b.x = curterm->sel.bx = 0;
156 curterm->sel.e.x = curterm->sel.ex = curterm->col;
157 curterm->sel.b.y = curterm->sel.e.y = curterm->sel.ey;
158 } else if (now-curterm->sel.tclick1 <= opt_doubleclick_timeout) {
159 /* double click to select word */
160 K8TLine l = k8t_selGet(curterm, curterm->sel.ey);
162 if (l != NULL) {
163 //FIXME: write better word selection code
164 curterm->sel.bx = curterm->sel.ex;
165 if (K8T_ISGFX(l[curterm->sel.bx].attr)) {
166 while (curterm->sel.bx > 0 && K8T_ISGFX(l[curterm->sel.bx-1].attr)) --curterm->sel.bx;
167 curterm->sel.b.x = curterm->sel.bx;
168 while (curterm->sel.ex < curterm->col-1 && K8T_ISGFX(l[curterm->sel.ex+1].attr)) ++curterm->sel.ex;
169 } else {
170 while (curterm->sel.bx > 0 && !K8T_ISGFX(l[curterm->sel.bx-1].attr) && l[curterm->sel.bx-1].c[0] != ' ') --curterm->sel.bx;
171 curterm->sel.b.x = curterm->sel.bx;
172 while (curterm->sel.ex < curterm->col-1 && !K8T_ISGFX(l[curterm->sel.ex+1].attr) && l[curterm->sel.ex+1].c[0] != ' ') ++curterm->sel.ex;
174 curterm->sel.e.x = curterm->sel.ex;
175 curterm->sel.b.y = curterm->sel.e.y = curterm->sel.ey;
179 k8t_selCopy(curterm);
180 k8t_drawTerm(curterm, 1);
181 } else {
182 // multiline or multichar selection
183 k8t_selCopy(curterm);
186 curterm->sel.tclick2 = curterm->sel.tclick1;
187 curterm->sel.tclick1 = mclock_ticks();
188 //k8t_drawTerm(1);
192 static void xevtcbbmotion (XEvent *e) {
193 if (curterm == NULL) return;
195 switch (opt_tabposition) {
196 case 0: // bottom
197 if (e->xbutton.y >= xw.h-xw.tabheight) { changeXCursor(1); return; }
198 break;
199 case 1: // top
200 if (e->xbutton.y < xw.tabheight) { changeXCursor(1); return; }
201 break;
203 changeXCursor(0);
205 if (curterm->sel.mode) {
206 int oldey = curterm->sel.ey, oldex = curterm->sel.ex;
208 getButtonInfo(curterm, e, NULL, &curterm->sel.ex, &curterm->sel.ey); // this sets sel.b and sel.e
209 if (oldey != curterm->sel.ey || oldex != curterm->sel.ex) {
210 int starty = K8T_MIN(oldey, curterm->sel.ey);
211 int endy = K8T_MAX(oldey, curterm->sel.ey);
213 k8t_tmDirty(curterm, starty, endy);
214 k8t_drawTerm(curterm, 1);
216 return;
218 //if (K8T_ISSET(curterm, K8T_MODE_MOUSE) && e->xbutton.button != 0) xdoMouseReport(curterm, e);