libxputty  0.1
A damn tiny abstraction Layer to create X11 window/widgets with cairo surfaces
xmenu_private.c
Go to the documentation of this file.
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 
22 #include "xmenu_private.h"
23 
24 
25 int _menu_remove_low_dash(char *str) {
26 
27  char *src;
28  char *dst;
29  int i = 0;
30  int r = 0;
31  for (src = dst = str; *src != '\0'; src++) {
32  *dst = *src;
33  if (*dst != '_') {
34  dst++;
35  } else {
36  r = i;
37  }
38  i++;
39  }
40  *dst = '\0';
41  return r;
42 }
43 
44 void _draw_menu_label(void *w_, void* user_data) {
45  Widget_t *w = (Widget_t*)w_;
46  XWindowAttributes attrs;
47  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
48  int width = attrs.width;
49  int height = attrs.height;
50 
51  cairo_text_extents_t extents;
53  cairo_set_font_size (w->crb, w->app->normal_font/w->scale.ascale);
54  cairo_text_extents(w->crb, "A", &extents);
55  double lh = extents.height;
56 
57  if (strstr(w->label, "_")) {
58  cairo_text_extents(w->crb, "--", &extents);
59  double underline = extents.width;
60  strcpy(w->input_label,w->label);
61  int pos = _menu_remove_low_dash(w->input_label);
62  cairo_text_extents(w->crb,w->input_label , &extents);
63  cairo_move_to (w->crb, (width-extents.width)*0.5, (height+lh)*0.5);
64  cairo_show_text(w->crb, w->input_label);
65  cairo_set_line_width(w->crb, 1.0);
66  cairo_move_to (w->crb, (width-extents.width)*0.5 + (pos * underline), (height+lh)*0.55);
67  cairo_line_to(w->crb,(width-extents.width)*0.5 + ((pos+1) * underline), (height+lh)*0.55);
68  cairo_stroke(w->crb);
69  } else {
70  cairo_text_extents(w->crb,w->label , &extents);
71  cairo_move_to (w->crb, (width-extents.width)*0.5, (height+lh)*0.5);
72  cairo_show_text(w->crb, w->label);
73  }
74 
75  cairo_new_path (w->crb);
76 }
77 
78 void _check_menu_state(void *w_, void* user_data) {
79  Widget_t *w = (Widget_t*)w_;
80  Widget_t *parent = w->parent;
81  int i = parent->childlist->elem-1;
82  for(;i>-1;i--) {
83  Widget_t *wid = parent->childlist->childs[i];
84  if (childlist_has_child(wid->childlist)) {
85  if ((wid->childlist->childs[0] == w->app->hold_grab) && (wid !=w)) {
86  XUngrabPointer(w->app->dpy,CurrentTime);
88  w->app->hold_grab = NULL;
89  pop_menu_show(w, w->childlist->childs[0], 6, true);
90  break;
91  }
92  }
93  }
94  transparent_draw(w_, user_data);
95 }
96 
97 void _menu_released(void *w_, void* button_, void* user_data) {
98  Widget_t *w = (Widget_t*)w_;
99  XButtonEvent *xbutton = (XButtonEvent*)button_;
100  if (w->flags & HAS_POINTER && xbutton->button == Button1) {
101  pop_menu_show(w, w->childlist->childs[0], 6, true);
102  }
103 }
104 
105 void _menu_entry_released(void *w_, void* item_, void* user_data) {
106  Widget_t *w = (Widget_t*)w_;
107  Widget_t * bar = NULL;
108  int i = w->app->childlist->elem-1;
109  for(;i>-1;i--) {
110  Widget_t *wid = w->app->childlist->childs[i];
111  if (wid == w) {
112  bar = w->app->childlist->childs[i-1];
113  int old_value = (int)adj_get_value(bar->adj);
114  adj_set_value(bar->adj, (float)*(int*)item_);
115  if (old_value == *(int*)item_)
116  bar->func.value_changed_callback(bar, NULL);
117  break;
118  }
119  }
120 }
121 
122 void _draw_menu(void *w_, void* user_data) {
123  Widget_t *w = (Widget_t*)w_;
124  if (!w) return;
126  cairo_paint (w->crb);
127 }
128 
129 void _draw_item(void *w_, void* user_data) {
130  Widget_t *w = (Widget_t*)w_;
131  if (!w) return;
132  XWindowAttributes attrs;
133  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
134  int width = attrs.width;
135  int height = attrs.height;
136  if (attrs.map_state != IsViewable) return;
137 
139  cairo_rectangle(w->crb, 0, 0, width , height);
140  if(w->state==1) {
142  } else if(w->state==2) {
144  } else if(w->state==3) {
146  }
147  cairo_fill_preserve(w->crb);
148  cairo_set_line_width(w->crb, 1.0);
150  cairo_stroke(w->crb);
151 
152  cairo_text_extents_t extents;
153  /** show label **/
155  cairo_set_font_size (w->crb, height/2);
156  cairo_text_extents(w->crb,w->label , &extents);
157  cairo_move_to (w->crb, (width-extents.width)*0.5, (height+extents.height)*0.5);
158  cairo_show_text(w->crb, w->label);
159  cairo_new_path (w->crb);
160 }
161 
162 void _draw_accel_item(void *w_, void* user_data) {
163  Widget_t *w = (Widget_t*)w_;
164  if (!w) return;
165  XWindowAttributes attrs;
166  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
167  int width = attrs.width;
168  int height = attrs.height;
169  if (attrs.map_state != IsViewable) return;
170 
172  cairo_rectangle(w->crb, 0, 0, width , height);
173  if(w->state==1) {
175  } else if(w->state==2) {
177  } else if(w->state==3) {
179  }
180  cairo_fill_preserve(w->crb);
181  cairo_set_line_width(w->crb, 1.0);
183  cairo_stroke(w->crb);
184 
185  cairo_text_extents_t extents;
186  /** show label **/
188  cairo_set_font_size (w->crb, height/2);
189 
190  if (strstr(w->label, "_")) {
191  cairo_text_extents(w->crb, "--", &extents);
192  double underline = extents.width;
193  strcpy(w->input_label,w->label);
194  int pos = _menu_remove_low_dash(w->input_label);
195  cairo_text_extents(w->crb,w->input_label , &extents);
196  cairo_move_to (w->crb, (width-extents.width)*0.5, (height+extents.height)*0.5);
197  cairo_show_text(w->crb, w->input_label);
198  cairo_set_line_width(w->crb, 1.0);
199  cairo_move_to (w->crb, (width-extents.width)*0.5 + (pos * underline), (height+extents.height)*0.55);
200  cairo_line_to(w->crb,(width-extents.width)*0.5 + ((pos+1) * underline), (height+extents.height)*0.55);
201  cairo_stroke(w->crb);
202  } else {
203  cairo_text_extents(w->crb,w->label , &extents);
204  cairo_move_to (w->crb, (width-extents.width)*0.5, (height+extents.height)*0.5);
205  cairo_show_text(w->crb, w->label);
206  }
207  cairo_new_path (w->crb);
208 }
209 
210 void _draw_check_item(void *w_, void* user_data) {
211  _draw_item(w_, user_data);
212  Widget_t *w = (Widget_t*)w_;
213  XWindowAttributes attrs;
214  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
215  int height = attrs.height;
216  if (w->flags & IS_RADIO) {
217  cairo_arc(w->crb, height/3, height/2, height/6, 0, 2 * M_PI );
218  } else {
219  cairo_rectangle(w->crb, height/6, height/3, height/3 , height/3);
220  }
222  cairo_fill(w->crb);
223  if ((int) w->adj_y->value) {
224  if (w->flags & IS_RADIO) {
225  cairo_arc(w->crb, height/3, height/2, height/6-2, 0, 2 * M_PI );
226  } else {
227  cairo_rectangle(w->crb, height/6+1, height/3+1, height/3-2 , height/3-2);
228  }
230  cairo_fill(w->crb);
231  }
232 }
233 
234 void _draw_viewslider(void *w_, void* user_data) {
235  Widget_t *w = (Widget_t*)w_;
236  int v = (int)w->adj->max_value;
237  if (!v) return;
238  XWindowAttributes attrs;
239  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
240  if (attrs.map_state != IsViewable) return;
241  int width = attrs.width;
242  int height = attrs.height;
243  float sliderstate = adj_get_state(w->adj);
245  cairo_rectangle(w->crb, width-5,0,5,height);
246  cairo_fill_preserve(w->crb);
248  cairo_fill(w->crb);
250  cairo_rectangle(w->crb, width-5,(height-10)*sliderstate,5,10);
251  cairo_fill_preserve(w->crb);
253  cairo_set_line_width(w->crb,1);
254  cairo_stroke(w->crb);
255 }
256 
257 void _set_viewpoint(void *w_, void* user_data) {
258  Widget_t *w = (Widget_t*)w_;
259  int v = (int)max(0,adj_get_value(w->adj));
260  XWindowAttributes attrs;
261  XGetWindowAttributes(w->app->dpy, (Window)w->childlist->childs[0]->widget, &attrs);
262  int height = attrs.height;
263  XMoveWindow(w->app->dpy,w->widget,0, -height*v);
264 }
265 
266 void _check_item_button_pressed(void *w_, void* button_, void* user_data) {
267  Widget_t *w = (Widget_t*)w_;
268  if (w->flags & HAS_FOCUS) {
269  float value = w->adj_y->value ? 0.0 : 1.0;
270  adj_set_value(w->adj_y, value);
271  }
272 }
273 
274 void _radio_item_button_pressed(void *w_, void* button_, void* user_data) {
275  Widget_t *w = (Widget_t*)w_;
276  if (w->flags & HAS_FOCUS) {
278  }
279 }
280 
281 void _configure_menu(Widget_t *parent, Widget_t *menu, int elem, bool above) {
282  Widget_t* view_port = menu->childlist->childs[0];
283  if (!view_port->childlist->elem) return;
284  XWindowAttributes attrs;
285  XGetWindowAttributes(menu->app->dpy, (Window)view_port->childlist->childs[0]->widget, &attrs);
286  int height = attrs.height;
287  int x1, y1;
288  int posy = (above) ? parent->height : 0;
289  Window child;
290  XTranslateCoordinates( parent->app->dpy, parent->widget, DefaultRootWindow(parent->app->dpy), 0, posy, &x1, &y1, &child );
291  int item_width = 1.0;
292  cairo_text_extents_t extents;
293  int i = view_port->childlist->elem-1;
294  set_adjustment(view_port->adj,0.0, view_port->adj->value, 0.0, i-(elem-1),1.0, CL_VIEWPORT);
295  bool is_not_scrolable = false;
296  if(view_port->childlist->elem <= elem) {
297  elem = view_port->childlist->elem;
298  is_not_scrolable = true;
299  }
300  for(;i>-1;i--) {
301  Widget_t *w = view_port->childlist->childs[i];
302  cairo_set_font_size (w->crb, height/2);
303  cairo_text_extents(w->crb,w->label , &extents);
304 
305  item_width = max(item_width, (int)extents.width+40);
306  if(is_not_scrolable) w->scale.gravity = NORTHEAST;
307  }
308  if(above) {
309  if(item_width<parent->width)item_width = parent->width;
310  }
311  XResizeWindow (menu->app->dpy, menu->widget, item_width, height*elem);
312  XResizeWindow (view_port->app->dpy, view_port->widget, item_width, height*view_port->childlist->elem);
313  XMoveWindow(menu->app->dpy,menu->widget,x1, y1);
314 }
use_text_color_scheme
void use_text_color_scheme(Widget_t *w, Color_state st)
use_text_color_scheme - use text Colors to paint on Widget_t
Definition: xcolor.c:199
Widget_t::width
int width
Definition: xwidget.h:352
Resize_t::gravity
Gravity gravity
Definition: xwidget.h:192
Xputty::childlist
Childlist_t * childlist
Definition: xputty.h:179
adj_get_state
float adj_get_state(Adjustment_t *adj)
adj_get_state - get the current state of the Adjustment_t
Definition: xadjustment.c:148
Adjustment_t::value
float value
Definition: xadjustment.h:86
_draw_check_item
void _draw_check_item(void *w_, void *user_data)
_draw_check_item - draw item on expose call
Definition: xmenu_private.c:210
Childlist_t::childs
Widget_t ** childs
Definition: xchildlist.h:51
get_color_state
Color_state get_color_state(Widget_t *wid)
get_color_state - get the Color_state to use in relation to the Widget_t state
Definition: xcolor.c:155
_draw_menu_label
void _draw_menu_label(void *w_, void *user_data)
_draw_menu_label - draw the menu label on expose call
Definition: xmenu_private.c:44
use_shadow_color_scheme
void use_shadow_color_scheme(Widget_t *w, Color_state st)
use_shadow_color_scheme - use shadow Colors to paint on Widget_t
Definition: xcolor.c:206
transparent_draw
void transparent_draw(void *wid, void *user_data)
transparent_draw - copy parent surface to child surface you usaualy didn't need to call this,...
Definition: xwidget.c:469
Xputty::normal_font
int normal_font
Definition: xputty.h:191
adj_get_value
float adj_get_value(Adjustment_t *adj)
adj_get_value - get the current value of the Adjustment_t
Definition: xadjustment.c:154
HAS_POINTER
@ HAS_POINTER
Definition: xwidget.h:247
Widget_t::crb
cairo_t * crb
Definition: xwidget.h:318
xmenu_private.h
HAS_FOCUS
@ HAS_FOCUS
Definition: xwidget.h:245
Widget_t::flags
long long flags
Definition: xwidget.h:324
adj_set_value
void adj_set_value(Adjustment_t *adj, float value)
adj_set_value - set the current value to the Adjustment_t
Definition: xadjustment.c:163
Widget_t::adj
Adjustment_t * adj
Definition: xwidget.h:334
use_fg_color_scheme
void use_fg_color_scheme(Widget_t *w, Color_state st)
use_fg_color_scheme - use forground Colors to paint on Widget_t
Definition: xcolor.c:178
Widget_t::scale
Resize_t scale
Definition: xwidget.h:356
_draw_viewslider
void _draw_viewslider(void *w_, void *user_data)
_draw_viewslider - draw a slider on the viewport to indicate the view point
Definition: xmenu_private.c:234
CL_VIEWPORT
@ CL_VIEWPORT
Definition: xadjustment.h:57
_check_menu_state
void _check_menu_state(void *w_, void *user_data)
_check_menu_state - follow the mouse pointer when a menu is active
Definition: xmenu_private.c:78
Xputty::hold_grab
Widget_t * hold_grab
Definition: xputty.h:185
use_bg_color_scheme
void use_bg_color_scheme(Widget_t *w, Color_state st)
use_bg_color_scheme - use background Colors to paint on Widget_t
Definition: xcolor.c:185
_draw_menu
void _draw_menu(void *w_, void *user_data)
_draw_menu - draw menu on expose call
Definition: xmenu_private.c:122
Widget_t::app
Xputty * app
Definition: xwidget.h:300
Xputty::dpy
Display * dpy
Definition: xputty.h:181
use_frame_color_scheme
void use_frame_color_scheme(Widget_t *w, Color_state st)
use_frame_color_scheme - use frame Colors to paint on Widget_t
Definition: xcolor.c:213
IS_RADIO
@ IS_RADIO
Definition: xwidget.h:239
_menu_released
void _menu_released(void *w_, void *button_, void *user_data)
_menu_released - popup the menu on click
Definition: xmenu_private.c:97
Widget_t::state
int state
Definition: xwidget.h:342
Resize_t::ascale
float ascale
Definition: xwidget.h:214
ACTIVE_
@ ACTIVE_
Definition: xcolor.h:42
_draw_item
void _draw_item(void *w_, void *user_data)
_draw_item - draw item on expose call
Definition: xmenu_private.c:129
Widget_t::widget
Window widget
Definition: xwidget.h:302
Widget_t
Widget_t - struct to hold the basic Widget_t info.
Definition: xwidget.h:298
NORMAL_
@ NORMAL_
Definition: xcolor.h:39
PRELIGHT_
@ PRELIGHT_
Definition: xcolor.h:40
_set_viewpoint
void _set_viewpoint(void *w_, void *user_data)
_set_viewpoint - move the view_port to position
Definition: xmenu_private.c:257
_draw_accel_item
void _draw_accel_item(void *w_, void *user_data)
_draw_accel_item - draw accel item on expose call
Definition: xmenu_private.c:162
Widget_t::height
int height
Definition: xwidget.h:354
radio_item_set_active
void radio_item_set_active(Widget_t *w)
radio_item_set_active - activate selected radio item
Definition: xmenu.c:171
Widget_t::childlist
Childlist_t * childlist
Definition: xwidget.h:336
Adjustment_t::max_value
float max_value
Definition: xadjustment.h:90
set_adjustment
void set_adjustment(Adjustment_t *adj, float std_value, float value, float min_value, float max_value, float step, CL_type type)
*set_adjustment - set a new range to a existing Adjustment_t it will be created if it not exsits yet
Definition: xadjustment.c:80
pop_menu_show
void pop_menu_show(Widget_t *parent, Widget_t *menu, int elem, bool above)
pop_menu_show - pop up a menu to a Widget_t
Definition: xmenu.c:26
_check_item_button_pressed
void _check_item_button_pressed(void *w_, void *button_, void *user_data)
_check_item_button_pressed - redraw item on button press
Definition: xmenu_private.c:266
Childlist_t::elem
int elem
Definition: xchildlist.h:57
_configure_menu
void _configure_menu(Widget_t *parent, Widget_t *menu, int elem, bool above)
_configure_menu - set final size and position of menu to a Widget_t
Definition: xmenu_private.c:281
Widget_t::input_label
char input_label[32]
Definition: xwidget.h:328
Widget_t::adj_y
Adjustment_t * adj_y
Definition: xwidget.h:332
Widget_t::func
Func_t func
Definition: xwidget.h:310
_menu_entry_released
void _menu_entry_released(void *w_, void *item_, void *user_data)
_menu_entry_released - the menu release func
Definition: xmenu_private.c:105
childlist_has_child
int childlist_has_child(Childlist_t *childlist)
childlist_has_child - check if a Widget_t Childlist_t contain a child
Definition: xchildlist.c:91
max
#define max(x, y)
max - set a minimal value (x) as return value
Definition: xputty.h:86
Widget_t::parent
void * parent
Definition: xwidget.h:304
use_base_color_scheme
void use_base_color_scheme(Widget_t *w, Color_state st)
use_base_color_scheme - use base Colors to paint on Widget_t
Definition: xcolor.c:192
_menu_remove_low_dash
int _menu_remove_low_dash(char *str)
Definition: xmenu_private.c:25
SELECTED_
@ SELECTED_
Definition: xcolor.h:41
Widget_t::label
const char * label
Definition: xwidget.h:326
Func_t::value_changed_callback
xevfunc value_changed_callback
Definition: xwidget.h:85
widget_hide
void widget_hide(Widget_t *w)
widget_hide - unmap/hide a Widget_t
Definition: xwidget.c:396
_radio_item_button_pressed
void _radio_item_button_pressed(void *w_, void *button_, void *user_data)
_radio_item_button_pressed - redraw item on button press
Definition: xmenu_private.c:274
NORTHEAST
@ NORTHEAST
Definition: xwidget.h:159