summaryrefslogtreecommitdiff
path: root/src/x.c
blob: 61a0fc0f723e566315a7204c107898edfd5b2e8e (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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/keysym.h>
#include <xcb/xcb_keysyms.h>

// #include <xcb/xcb_cursor.h> very versatile

#include "x.h"
#include "types.h"
#include "config.h"
#include "scapx.h"

Server_context_t *init_XCB_server();
xcb_window_t create_win(Server_context_t *info);

Server_context_t *init_XCB_server()
{
	Server_context_t *info;

	if (!(info = malloc(sizeof(Server_context_t)))) {
		fprintf(stderr, "memory allocation failed.\n");
		return NULL;
	}

	info->con = xcb_connect(NULL, &info->scr_nbr);
	if (xcb_connection_has_error(info->con) > 0) {
		fprintf(stderr, "Error opening display.\n");
		free(info); return NULL;
	}

	info->iter = xcb_setup_roots_iterator(xcb_get_setup(info->con));
	for (; info->iter.rem; --info->scr_nbr, xcb_screen_next(&info->iter))
		if (info->scr_nbr == 0) {
			info->scr = info->iter.data;
			break;
		}

	return info;
}

xcb_window_t create_win(Server_context_t *info)
{
	xcb_gcontext_t gc;
	xcb_window_t win;
	u32 vmask, vlist[2];

	// create gc
	win = info->scr->root;
	gc = xcb_generate_id(info->con);
	vmask = XCB_GC_FOREGROUND         |
		    /*
		    XCB_GC_LINE_WIDTH         |
		    XCB_GC_LINE_STYLE         |
		    XCB_GC_FILL_STYLE         |
			XCB_GC_ARC_MODE           |
			*/
		    XCB_GC_GRAPHICS_EXPOSURES;
	vlist[0] = info->scr->black_pixel;
	vlist[1] = 0;
	xcb_create_gc (info->con, gc, win, vmask, vlist);

	// create window
	win = xcb_generate_id(info->con);
	vmask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
	vlist[0] = /* 0 */ info->scr->white_pixel;
	vlist[1] = XCB_EVENT_MASK_EXPOSURE        | // window is exposed, needs to be redrawn
		       XCB_EVENT_MASK_BUTTON_PRESS    |
		       XCB_EVENT_MASK_BUTTON_RELEASE  |
		   	   XCB_EVENT_MASK_BUTTON_1_MOTION | // mouse is dragging
		   	   XCB_EVENT_MASK_POINTER_MOTION  | // mouse is moving without clicking
			   XCB_MOTION_NOTIFY              |
			   XCB_EVENT_MASK_BUTTON_MOTION   |
			   XCB_EVENT_MASK_LEAVE_WINDOW    |
			   /*
			   XCB_MOTION_NOTIFY              |
			   XCB_EVENT_MASK_EXPOSURE        |
			   XCB_EVENT_MASK_BUTTON_PRESS    |
			   XCB_EVENT_MASK_BUTTON_RELEASE; // keyboard
			   XCB_KEY_PRESS                  |
			   XCB_EVENT_MASK_KEY_PRESS       |
			   */
			   XCB_KEY_PRESS                  |
			   XCB_KEY_RELEASE;

	xcb_create_window(info->con,
					  XCB_COPY_FROM_PARENT,
					  win,
					  info->scr->root,
					  0, 0,
					  info->scr->width_in_pixels,
					  info->scr->height_in_pixels,
					  10, // boarder width
					  XCB_WINDOW_CLASS_INPUT_OUTPUT,
					  info->scr->root_visual,
					  vmask, vlist
			   		 );

	xcb_map_window(info->con, win);
	xcb_flush(info->con);

	return win;
}

xcb_cursor_t cursor_set(xcb_connection_t *c, xcb_window_t win, u32 cid)
{
	xcb_font_t font;
	xcb_cursor_t ptr;
	u32 mask;
	u32 value_list;

	font = xcb_generate_id(c);
	xcb_open_font(c, font, strlen("cursor"), "cursor");
	ptr = xcb_generate_id(c);
	xcb_create_glyph_cursor(c,
			                ptr,
			                font, font,
			                cid, cid,
			                0, 0, 0,
			                0, 0, 0);

	mask = XCB_CW_CURSOR;
	value_list = ptr;
	xcb_change_window_attributes(c, win, mask, &value_list);
	xcb_flush(c);

	return ptr;
}

void cursor_die(xcb_connection_t *c, xcb_window_t win, u32 value_list)
{
	value_list = 0;
	xcb_change_window_attributes(c, win, XCB_CW_CURSOR, &value_list);
	// xcb_free_cursor(c, value_list);
	xcb_flush(c);
}

const char *ksym_to_str(const xcb_keysym_t *ksym)
{
	switch (*ksym) {
		case XK_Escape: return "Escape";
		case XK_q:      return "q";
		case XK_Q:      return "Q";
		case XK_l:      return "l";
		case XK_w:      return "w";
		case XK_c:      return "c";
		case XK_r:      return "r";
		default:        return NULL;
	}

	return NULL;
}

void die(xcb_key_symbols_t *sym, Server_context_t *s_info, xcb_drawable_t win)
{
	xcb_key_symbols_free(sym);
	xcb_free_gc(s_info->con, win);
	xcb_disconnect(s_info->con);
	free(s_info);
	exit(0);
}

xcb_window_t get_focused_win(xcb_connection_t *con)
{
	xcb_get_input_focus_reply_t *in_fo_reply = NULL;

	in_fo_reply = xcb_get_input_focus_reply(con, xcb_get_input_focus(con), NULL);
	if (!in_fo_reply) {
		DEBUG_INFO("could not get input focus reply: %s\n", "");
		return XCB_WINDOW_NONE;
	}

	xcb_window_t focused_win = in_fo_reply->focus;
	free(in_fo_reply);

	if (focused_win == XCB_WINDOW_NONE) {
		DEBUG_INFO("could not retrieve focused window: %s\n", "");
		return XCB_WINDOW_NONE;
	}

	return focused_win;
}

xcb_atom_t get_atom(xcb_connection_t *c, const char *atom_name)
{
	xcb_intern_atom_cookie_t cookie = xcb_intern_atom(c, 0, strlen(atom_name), atom_name);
	xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(c, cookie, NULL);
	xcb_atom_t atom = reply->atom;
	free(reply);

	return atom;
}

void xcb_set_win_name(xcb_connection_t *c, xcb_window_t w, const char *title)
{
	xcb_atom_t WM_NAME = get_atom(c, "WM_NAME");
	xcb_atom_t STRING = get_atom(c, "STRING");
	xcb_change_property(c, XCB_PROP_MODE_REPLACE, w, WM_NAME, STRING, 8,
	                    strlen(title), title);

	xcb_map_window (c, w);
	xcb_flush (c);
}