1 /*
2 * 0BSD
3 *
4 * BSD Zero Clause License
5 *
6 * Copyright (c) 2019 Hermann Meyer
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted.
10
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21 #include "xputty.h"
22
23
main_init(Xputty * main)24 void main_init(Xputty *main) {
25 main->dpy = XOpenDisplay(0);
26 assert(main->dpy);
27 main->childlist = (Childlist_t*)malloc(sizeof(Childlist_t));
28 assert(main->childlist);
29 childlist_init(main->childlist);
30 main->color_scheme = (XColor_t*)malloc(sizeof(XColor_t));
31 assert(main->color_scheme);
32 set_dark_theme(main);
33 main->hold_grab = NULL;
34 main->submenu = NULL;
35 main->run = true;
36 main->small_font = 10;
37 main->normal_font = 12;
38 main->big_font = 16;
39 main->ctext = NULL;
40 main->csize = 0;
41
42 main->dnd_source_window = 0;
43 main->dnd_version = 5;
44 main->XdndAware = XInternAtom (main->dpy, "XdndAware", False);
45 main->XdndTypeList = XInternAtom (main->dpy, "XdndTypeList", False);
46 main->XdndSelection = XInternAtom (main->dpy, "XdndSelection", False);
47 main->XdndStatus = XInternAtom (main->dpy, "XdndStatus", False);
48 main->XdndEnter = XInternAtom (main->dpy, "XdndEnter", False);
49 main->XdndPosition = XInternAtom (main->dpy, "XdndPosition", False);
50 main->XdndLeave = XInternAtom (main->dpy, "XdndLeave", False);
51 main->XdndDrop = XInternAtom (main->dpy, "XdndDrop", False);
52 main->XdndActionCopy = XInternAtom (main->dpy, "XdndActionCopy", False);
53 main->XdndFinished = XInternAtom (main->dpy, "XdndFinished", False);
54 main->dnd_type_uri = XInternAtom (main->dpy, "text/uri-list", False);
55 main->dnd_type_text = XInternAtom (main->dpy, "text/plain", False);
56 main->dnd_type_utf8 = XInternAtom (main->dpy, "UTF8_STRING", False);
57 main->dnd_type = None;
58
59 main->selection = XInternAtom(main->dpy, "CLIPBOARD", 0);
60 main->targets_atom = XInternAtom(main->dpy, "TARGETS", 0);
61 main->text_atom = XInternAtom(main->dpy, "TEXT", 0);
62 main->UTF8 = XInternAtom(main->dpy, "UTF8_STRING", 1);
63 if (main->UTF8 == None) main->UTF8 = XA_STRING;
64 }
65
main_run(Xputty * main)66 void main_run(Xputty *main) {
67 Widget_t * wid = main->childlist->childs[0];
68 Atom WM_DELETE_WINDOW;
69 WM_DELETE_WINDOW = XInternAtom(main->dpy, "WM_DELETE_WINDOW", True);
70 XSetWMProtocols(main->dpy, wid->widget, &WM_DELETE_WINDOW, 1);
71
72 XEvent xev;
73 int ew;
74
75 while (main->run && (XNextEvent(main->dpy, &xev)>=0)) {
76 if (XFilterEvent(&xev, None)) continue;
77 ew = childlist_find_widget(main->childlist, xev.xany.window);
78 if(ew >= 0) {
79 Widget_t * w = main->childlist->childs[ew];
80 w->event_callback(w, &xev, main, NULL);
81 }
82
83 switch (xev.type) {
84 case ButtonPress:
85 {
86 bool is_item = False;
87 if(main->submenu != NULL) {
88 if (childlist_has_child(main->submenu->childlist)) {
89 Widget_t *slider = main->submenu->childlist->childs[1];
90 if (xev.xbutton.window == slider->widget) {
91 break;
92 }
93 Widget_t *view_port = main->submenu->childlist->childs[0];
94 int i = view_port->childlist->elem-1;
95 for(;i>-1;i--) {
96 Widget_t *w = view_port->childlist->childs[i];
97 if (xev.xbutton.window == w->widget) {
98 is_item = True;
99 break;
100 }
101 }
102 }
103 }
104 if(main->hold_grab != NULL) {
105 if (childlist_has_child(main->hold_grab->childlist)) {
106 Widget_t *slider = main->hold_grab->childlist->childs[1];
107 if (xev.xbutton.window == slider->widget) {
108 break;
109 }
110 Widget_t *view_port = main->hold_grab->childlist->childs[0];
111 int i = view_port->childlist->elem-1;
112 for(;i>-1;i--) {
113 Widget_t *w = view_port->childlist->childs[i];
114 if (xev.xbutton.window == w->widget) {
115 is_item = True;
116 break;
117 }
118 }
119 if (xev.xbutton.window == view_port->widget) is_item = True;
120 }
121 if (!is_item) {
122 XUngrabPointer(main->dpy,CurrentTime);
123 widget_hide(main->hold_grab);
124 main->hold_grab = NULL;
125 }
126 }
127 }
128 break;
129 case ClientMessage:
130 {
131 if (xev.xclient.data.l[0] == (long int)WM_DELETE_WINDOW &&
132 xev.xclient.window == wid->widget) {
133 main->run = false;
134 } else if (xev.xclient.data.l[0] == (long int)WM_DELETE_WINDOW) {
135 int i = childlist_find_widget(main->childlist, xev.xclient.window);
136 if(i<1) return;
137 Widget_t *w = main->childlist->childs[i];
138 if(w->flags & HIDE_ON_DELETE) widget_hide(w);
139 else destroy_widget(main->childlist->childs[i],main);
140 }
141 break;
142 }
143 }
144 }
145 }
146
run_embedded(Xputty * main)147 void run_embedded(Xputty *main) {
148
149 XEvent xev;
150 int ew = -1;
151
152 while (XPending(main->dpy) > 0) {
153 XNextEvent(main->dpy, &xev);
154 if (xev.type == ClientMessage || xev.type == SelectionNotify) {
155 Widget_t * w = main->childlist->childs[0];
156 w->event_callback(w, &xev, main, NULL);
157 }
158 ew = childlist_find_widget(main->childlist, xev.xany.window);
159 if(ew >= 0) {
160 Widget_t * w = main->childlist->childs[ew];
161 w->event_callback(w, &xev, main, NULL);
162 }
163 switch (xev.type) {
164 case ButtonPress:
165 {
166 bool is_item = False;
167 if(main->hold_grab != NULL) {
168 if (childlist_has_child(main->hold_grab->childlist)) {
169 Widget_t *slider = main->hold_grab->childlist->childs[1];
170 if (xev.xbutton.window == slider->widget) {
171 break;
172 }
173 Widget_t *view_port = main->hold_grab->childlist->childs[0];
174 int i = view_port->childlist->elem-1;
175 for(;i>-1;i--) {
176 Widget_t *w = view_port->childlist->childs[i];
177 if (xev.xbutton.window == w->widget) {
178 is_item = True;
179 break;
180 }
181 }
182 if (xev.xbutton.window == view_port->widget) is_item = True;
183 }
184 if (!is_item) {
185 XUngrabPointer(main->dpy,CurrentTime);
186 widget_hide(main->hold_grab);
187 main->hold_grab = NULL;
188 }
189 }
190 }
191 break;
192 case ClientMessage:
193 if (xev.xclient.data.l[0] == (long int)XInternAtom(main->dpy, "WM_DELETE_WINDOW", True) ) {
194 int i = childlist_find_widget(main->childlist, xev.xclient.window);
195 if(i<1) return;
196 Widget_t *w = main->childlist->childs[i];
197 if(w->flags & HIDE_ON_DELETE) widget_hide(w);
198 else destroy_widget(w, main);
199 }
200 break;
201 }
202 }
203 }
204
main_quit(Xputty * main)205 void main_quit(Xputty *main) {
206 int i = main->childlist->elem-1;
207 for(;i>-1;i--) {
208 Widget_t *w = main->childlist->childs[i];
209 destroy_widget(w, main);
210 }
211 childlist_destroy(main->childlist);
212 free(main->childlist);
213 free(main->color_scheme);
214 XCloseDisplay(main->dpy);
215 free(main->ctext);
216 debug_print("quit\n");
217 }
218