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 #pragma once 22 23 #ifndef XWIDGET_H 24 #define XWIDGET_H 25 26 #include "xputty.h" 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 /*--------------------------------------------------------------------- 33 ----------------------------------------------------------------------- 34 basic X11 widgets 35 ----------------------------------------------------------------------- 36 ----------------------------------------------------------------------*/ 37 38 #define SYSTEM_TRAY_REQUEST_DOCK 0 39 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 40 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 41 42 /** 43 * @brief *vfunc - function pointer to connect Xevents from the main loop to Widget_t 44 * @param *widget - void pointer to the Widget_t 45 * @param *main - pointer to Xputty main struct running the loop 46 * @param *event - void pointer to the XEvent 47 * @param *user_data - void pointer to attached user_data, maybe NULL 48 * @return void 49 */ 50 51 typedef void (*vfunc)(void * widget, void * event, Xputty *main, void* user_data); 52 53 /** 54 * @brief *evfunc - function pointer to connect Xevents from a Widget_t to a event handler 55 * @param *widget - void pointer to the Widget_t 56 * @param *event - void pointer to the XEvent 57 * @param *user_data - void pointer to attached user_data, maybe NULL 58 * @return void 59 */ 60 61 typedef void (*evfunc)(void * widget, void * event, void* user_data); 62 63 64 /** 65 * @brief *xevfunc - function pointer to connect XEvents from a Widget_t to a event handler 66 * @param *widget - void pointer to the widget 67 * @param *user_data - void pointer to attached user_data, maybe NULL 68 * @return void 69 */ 70 71 typedef void (*xevfunc)(void * widget, void* user_data); 72 73 /** 74 * 75 * @brief Func_t - struct to hold all supported event callbacks 76 * 77 */ 78 79 typedef struct { 80 xevfunc expose_callback; 81 xevfunc configure_callback; 82 xevfunc enter_callback; 83 xevfunc leave_callback; 84 xevfunc adj_callback; 85 xevfunc value_changed_callback; 86 xevfunc user_callback; 87 xevfunc mem_free_callback; 88 xevfunc configure_notify_callback; 89 xevfunc map_notify_callback; 90 xevfunc unmap_notify_callback; 91 xevfunc dialog_callback; 92 93 evfunc button_press_callback; 94 evfunc button_release_callback; 95 evfunc motion_callback; 96 evfunc key_press_callback; 97 evfunc key_release_callback; 98 } Func_t; 99 100 /** 101 * 102 * @brief EventType - enum to hold identifier for all supported event callbacks 103 * \n Events could be connected to a handler by using this identifier 104 * @param EXPOSE - (*xevfunc) expose_callback(void * widget, void* user_data) 105 * @param CONFIGURE - (*xevfunc) configure_callback(void * widget, void* user_data) 106 * @param ENTER - (*xevfunc) enter_callback(void * widget, void* user_data) 107 * @param LEAVE - (*xevfunc) leave_callback(void * widget, void* user_data) 108 * @param ADJ_INTERN - (*xevfunc) adj_callback(void * widget, void* user_data) 109 * @param VALUE_CHANGED - (*xevfunc) value_changed_callback(void * widget, void* user_data) 110 * @param USER - (*xevfunc) user_callback(void * widget, void* user_data) 111 * @param MEM_FREE - (*xevfunc) mem_free_callback(void * widget, void* user_data) 112 * @param CONFIGURE_NOTIFY - (*xevfunc) configure_notify_callback(void * widget, void* user_data) 113 * @param MAP_NOTIFY - (*xevfunc) map_notify_callback(void * widget, void* user_data) 114 * @param UNMAP_NOTIFY - (*xevfunc) unmap_notify_callback(void * widget, void* user_data) 115 * @param DIALOG_RESPONS - (*xevfunc) dialog_callback(void * widget, void* user_data) 116 * @param BUTTON_PRESS - (*evfunc) button_press_callback(void * widget, void * event, void* user_data) 117 * @param BUTTON_RELEASE - (*evfunc) button_release_callback(void * widget, void * event, void* user_data) 118 * @param POINTER_MOTION - (*evfunc) motion_callback(void * widget, void * event, void* user_data) 119 * @param KEY_PRESS - (*evfunc) key_press_callback(void * widget, void * event, void* user_data) 120 * @param KEY_RELEASE - (*evfunc) key_release_callback(void * widget, void * event, void* user_data) 121 */ 122 123 typedef enum { 124 EXPOSE = 1, 125 CONFIGURE, 126 ENTER, 127 LEAVE, 128 ADJ_INTERN, 129 VALUE_CHANGED, 130 USER, 131 MEM_FREE, 132 CONFIGURE_NOTIFY, 133 MAP_NOTIFY, 134 UNMAP_NOTIFY, 135 DIALOG_RESPONSE, 136 BUTTON_PRESS, 137 BUTTON_RELEASE, 138 POINTER_MOTION, 139 KEY_PRESS, 140 KEY_RELEASE, 141 } EventType; 142 143 /** 144 * 145 * @brief Gravity - enum to indicate how to resize a widget 146 * @param NORTHWEST - Widget_t adjust nord/west 147 * @param NORTHEAST - Widget_t adjust nord/east 148 * @param SOUTHWEST - Widget_t adjust south/west 149 * @param SOUTHEAST - Widget_t adjust south/east 150 * @param CENTER - Widget_t adjust centered 151 * @param ASPECT - Widget_t adjust in a aspect frame 152 * @param NONE - Widget_t request no adjustment in frame 153 */ 154 155 typedef enum { 156 /** Widget_t adjust nord/west */ 157 NORTHWEST , 158 /** Widget_t adjust nord/east */ 159 NORTHEAST , 160 /** Widget_t adjust south/west */ 161 SOUTHWEST , 162 /** Widget_t adjust south/east */ 163 SOUTHEAST , 164 /** Widget_t adjust centered */ 165 CENTER , 166 /** Widget_t adjust in a aspect frame */ 167 ASPECT , 168 /** Widget_t adjust in a aspect frame */ 169 MENUITEM , 170 /** Widget_t request no adjustment in frame */ 171 NONE , 172 }Gravity; 173 174 /** 175 * 176 * @brief Resize_t - struct used to resize child widgets 177 * @param init_x - initial x position on Parent 178 * @param init_y - initial y position on Parent 179 * @param init_width - initial width 180 * @param init_height - initial height 181 * @param scale_x - scalling size of the x axsis 182 * @param scale_y - scalling size of the y axsis 183 * @param cscale_x - scalling factor of the x axsis 184 * @param cscale_y - scalling factor of the y axsis 185 * @param ascale - scalling factor for aspect scalling 186 */ 187 188 typedef struct { 189 /** indicate how the widget wish to be resized */ 190 Gravity gravity; 191 /** initial x position on Parent */ 192 int init_x; 193 /** initial y position on Parent */ 194 int init_y; 195 /** initial width */ 196 int init_width; 197 /** initial height */ 198 int init_height; 199 /** scalling size of the x axsis */ 200 float scale_x; 201 /** scalling size of the y axsis */ 202 float scale_y; 203 /** scalling factor of the x axsis */ 204 float cscale_x; 205 /** scalling factor of the y axsis */ 206 float cscale_y; 207 /** rescalling factor of the x axsis */ 208 float rcscale_x; 209 /** rescalling factor of the y axsis */ 210 float rcscale_y; 211 /** scalling factor for aspect scalling */ 212 float ascale; 213 } Resize_t; 214 215 /** 216 * 217 * @brief anonymous enum - flags to set Widget_t propertys 218 * @param IS_WIDGET - Widget_t is a sub widget 219 * @param IS_WINDOW - Widget_t has no Widget_t parent 220 * @param IS_POPUP - Widget_t is a pop up widget 221 * @param IS_RADIO - Widget_t is part of a radio group 222 * @param USE_TRANSPARENCY - Widget_t need transparent draw (buffer) 223 * @param HAS_FOCUS - Mouse pointer is above Widget_t 224 * @param HAS_POINTER - Mouse pointer is pressed on Widget_t 225 * @param HAS_TOOLTIP - Widget_t have tooltip 226 * @param HAS_MEM - Widget_t have mem to be released 227 */ 228 229 enum { 230 /** Widget_t is a sub widget */ 231 IS_WIDGET = 1<<0, 232 /** Widget_t has no Widget_t parent */ 233 IS_WINDOW = 1<<1, 234 /** Widget_t is a pop up widget */ 235 IS_POPUP = 1<<2, 236 /** Widget_t is part of a radio group */ 237 IS_RADIO = 1<<3, 238 /** Widget_t is a tooltip widget */ 239 IS_TOOLTIP = 1<<4, 240 /** Widget_t need transparent draw (buffer) */ 241 USE_TRANSPARENCY = 1<<5, 242 /** Mouse pointer is above Widget_t */ 243 HAS_FOCUS = 1<<6, 244 /** Mouse pointer is pressed on Widget_t */ 245 HAS_POINTER = 1<<7, 246 /** Widget_t have tooltip */ 247 HAS_TOOLTIP = 1<<8, 248 /** Widget_t have mem to be released */ 249 HAS_MEM = 1<<9, 250 /** Widget_t didn't receive autorepeated keys */ 251 NO_AUTOREPEAT = 1<<10, 252 /** Widget_t need fast redrawing */ 253 FAST_REDRAW = 1<<11, 254 /** Hide Widget_t instead delete on "WM_DELETE_WINDOW" */ 255 HIDE_ON_DELETE = 1<<12, 256 /** Widget_t reuse a surface from a other Widget_t */ 257 REUSE_IMAGE = 1<<13, 258 }; 259 260 /** 261 * 262 * @brief Widget_t - struct to hold the basic Widget_t info 263 * @param *app - pointer to the main struct 264 * @param widget - the X11 Window 265 * @param *parent - pointer to the Parent Window or Widget_t 266 * @param event_callback - the main XEvent callback 267 * @param func - struct holding the event callbacks 268 * @param *surface - pointer to the cairo xlib surface 269 * @param *cr - pointer to the cairo xlib surface context 270 * @param *buffer - pointer to the cairo buffer surface 271 * @param *crb - pointer to the cairo buffer surface context 272 * @param *image - pointer to the cairo image surface 273 * @param data - int to hold user data 274 * @param flags - unsigned int to hold Widget_t flags 275 * @param *label - pointer to the widget label 276 * @param input_label - char array the widget input label 277 * @param state - int to hold the widget state 278 * @param pos_x - mouse pointer x position on button press 279 * @param pos_y - mouse pointer y position on button press 280 * @param x - x position of Window on Parent 281 * @param y - y position of Window on Parent 282 * @param width - widget width 283 * @param height - widget height 284 * @param scale - struct used to resize child widgets 285 * @param *adj_x - pointer to the x axis adjustment 286 * @param *adj_y - pointer to the y axis adjustment 287 * @param *adj - pointer to the adjustment in use 288 * @param *childlist - pointer to Widget_t child list 289 * @param xic - Locale and UTF 8 support interface 290 * @param xim - Context to Locale and UTF 8 support 291 */ 292 293 struct Widget_t { 294 /** pointer to the main struct */ 295 Xputty *app; 296 /** the X11 newly created Window */ 297 Window widget; 298 /** pointer to the Parent Window or Widget_t */ 299 void *parent; 300 /** pointer to the Parent struct */ 301 void *parent_struct; 302 /** the main XEvent callback */ 303 vfunc event_callback; 304 /** struct holding the event callbacks */ 305 Func_t func; 306 /** pointer to the cairo xlib surface */ 307 cairo_surface_t *surface; 308 /** pointer to the cairo xlib surface context */ 309 cairo_t *cr; 310 /** pointer to the cairo buffer surface used for transparency */ 311 cairo_surface_t *buffer; 312 /** pointer to the cairo buffer surface context */ 313 cairo_t *crb; 314 /** pointer to the cairo image surface used to load a png */ 315 cairo_surface_t *image; 316 /** int to hold user data */ 317 int data; 318 /** int to hold Widget_t flags */ 319 long int flags; 320 /** pointer to the widget label */ 321 const char* label; 322 /** char array to hold user input */ 323 char input_label[32]; 324 /** pointer to the x axis adjustment */ 325 Adjustment_t *adj_x; 326 /** pointer to the y axis adjustment */ 327 Adjustment_t *adj_y; 328 /** pointer to the adjustment in use*/ 329 Adjustment_t *adj; 330 /** pointer to Widget_t child list */ 331 Childlist_t *childlist; 332 /** Locale and UTF 8 support */ 333 XIC xic; 334 /** Context to Locale and UTF 8 support */ 335 XIM xim; 336 /** int to hold the widget state default = 0 */ 337 int state; 338 /** mouse pointer x position on button press */ 339 int pos_x; 340 /** mouse pointer y position on button press */ 341 int pos_y; 342 /** x position of Window related to the Parent */ 343 int x; 344 /** y position of Window related to the Parent */ 345 int y; 346 /** the widget size x-axis */ 347 int width; 348 /** the widget size y-axis */ 349 int height; 350 /** struct used to resize child widgets */ 351 Resize_t scale; 352 }; 353 354 355 /** 356 * @brief *create_window - create a Window 357 * \n You need to create as least minimun one Window to get started. 358 * \n The first created Window is the top_level_widget() 359 * \n A Window could be created on the DefaultRootWindow() or embeded 360 * into a other XWindow 361 * @param *app - pointer to the Xputty *main struct to use 362 * @param win - pointer to the Parrent Window (may be Root) 363 * @param x,y,width,height - the position/geometry to create the window 364 * @return Widget_t * - pointer to the Widget_t struct 365 */ 366 367 Widget_t *create_window(Xputty *app, Window win, 368 int x, int y, int width, int height); 369 370 /** 371 * @brief *create_widget - create a widget 372 * \n A Widget_t could only be created as child of a other Widget_t 373 * \n To create a Widget_t you need to create a Widget_t with create_window() 374 * before. 375 * @param *app - pointer to the Xputty *main struct to use 376 * @param *parent - pointer to the Parrent Widget_t 377 * @param x,y,width,height - the position/geometry to create the widget 378 * @return Widget_t* - pointer to the Widget_t struct 379 */ 380 381 Widget_t *create_widget(Xputty *app, Widget_t *win, 382 int x, int y, int width, int height); 383 384 /** 385 * @brief connect_func - connect a event with a handler 386 * without type check. For supported events see: Func_t 387 * @param **event - the event to connect 388 * @param *handler - the handler to handle the event 389 * @return void 390 */ 391 392 void connect_func(void (**event)(), void (*handler)()); 393 394 /** 395 * @brief widget_set_title - set window title for a Widget_t 396 * @param *w - pointer to the Widget_t to set the title 397 * @param *title - the title to store 398 * @return void 399 */ 400 401 void widget_set_title(Widget_t *w, const char *title); 402 403 /** 404 * @brief widget_show - map/show widget 405 * @param *w - pointer to the Widget_t to map 406 * @return void 407 */ 408 409 void widget_show(Widget_t *w); 410 411 /** 412 * @brief pop_widget_show_all - map/show popup widget with all it's childs 413 * @param *w - pointer to the Widget_t to map 414 * @return void 415 */ 416 417 void pop_widget_show_all(Widget_t *w); 418 419 /** 420 * @brief widget_hide - unmap/hide a Widget_t 421 * @param *w - pointer to the Widget_t to unmap 422 * @return void 423 */ 424 425 void widget_hide(Widget_t *w); 426 427 /** 428 * @brief widget_show_all - map/show Widget_t with all childs 429 * @param *w - pointer to the Widget_t to map 430 * @return void 431 */ 432 433 void widget_show_all(Widget_t *w); 434 435 /** 436 * @brief show_tooltip - check if a Widget_t have a tooltip, 437 * and show it, if a tooltip is available. 438 * @param *wid - pointer to the Widget_t receiving the event 439 * @return void 440 */ 441 442 void show_tooltip(Widget_t *wid); 443 444 /** 445 * @brief hide_tooltip - check if a Widget_t have a tooltip, 446 * and hide it, if a tooltip is mapped. 447 * @param *wid - pointer to the Widget_t receiving the event 448 * @return void 449 */ 450 451 void hide_tooltip(Widget_t *wid); 452 453 /** 454 * @brief *get_toplevel_widget - get pointer to the top level Widget_t 455 * @param *main - pointer to the main Xputty struct 456 * @return void 457 */ 458 459 Widget_t *get_toplevel_widget(Xputty *main); 460 461 /** 462 * @brief quit - exit the main loop 463 * @param *w - pointer to the Widget_t sending the request 464 * @return void 465 */ 466 467 void quit(Widget_t *w); 468 469 /** 470 * @brief quit_widget - remove a widget from the processing loop 471 * @param *w - pointer to the Widget_t sending the request 472 * @return void 473 */ 474 475 void quit_widget(Widget_t *w); 476 477 /** 478 * @brief transparent_draw - copy parent surface to child surface 479 * \n you usaualy didn't need to call this, it's used automaticaly 480 * when a Widget_t have set the flag USE_TRANSPARENCY 481 * \n this is the default setting for Widget_t 482 * @param *wid - pointer to the Widget_t receiving the event 483 * @param *user_data - void pointer to attached user_data 484 * @return void 485 */ 486 487 void transparent_draw(void * wid, void* user_data); 488 489 /** 490 * @brief widget_reset_scale - used to reset scaling mode after a image surface 491 * is drawn to the Widget_t surface with widget_set_scale() 492 * @param *w - pointer to the Widget_t sending the request 493 * @return void 494 */ 495 496 void widget_reset_scale(Widget_t *w); 497 498 /** 499 * @brief widget_set_scale - set scaling mode to scale a image surface 500 * to the size of the Widget_t surface 501 * @param *w - pointer to the Widget_t sending the request 502 * @return void 503 */ 504 505 void widget_set_scale(Widget_t *w); 506 507 /** 508 * @brief destroy_widget - destroy a widget 509 * \n When a Widget_t receive a destroy_widget() call, it will propagate that 510 * to all childs in it's Childlist_t. So all childs get destroyed before the 511 * Widget_t itself close. 512 * @param *w - pointer to the Widget_t sending the request 513 * @param *main - pointer to main struct 514 * @return void 515 */ 516 517 void destroy_widget(Widget_t *w, Xputty *main); 518 519 /** 520 * @brief widget_event_loop - the internal widget event loop 521 * @param *w - void pointer to the Widget_t receiving the event 522 * @param *event - void pointer to the XEvent 523 * @param *main - void pointer to the Xputty *main struct running 524 * the event loop 525 * @param *user_data - void pointer to attached user_data 526 * @return void 527 */ 528 529 void widget_event_loop(void *w_, void* event, Xputty *main, void* user_data); 530 531 /** 532 * @brief send_configure_event - send a ConfigureNotify to Widget_t 533 * \n used to resize a Widget_t 534 * @param *w - pointer to the Widget_t to send the notify 535 * @param x,y - the new Widget_t position 536 * @param width,height - the new Widget_t size 537 * @return void 538 */ 539 540 void send_configure_event(Widget_t *w,int x, int y, int width, int height); 541 542 /** 543 * @brief send_button_press_event - send ButtonPress event to Widget_t 544 * \n simulate a BUTTON_PRESS Event 545 * @param *w - pointer to the Widget_t to send the notify 546 * @return void 547 */ 548 549 void send_button_press_event(Widget_t *w); 550 551 /** 552 * @brief send_button_release_event - send ButtonRelease event to Widget_t 553 * \n simulate a BUTTON_RELEASE Event 554 * @param *w - pointer to the Widget_t to send the notify 555 * @return void 556 */ 557 558 void send_button_release_event(Widget_t *w); 559 560 /** 561 * @brief send_systray_message - request a systray icon for Widget_t 562 * \n currently not working 563 * @param *w - pointer to the Widget_t to send the notify 564 * @return void 565 */ 566 567 void send_systray_message(Widget_t *w); 568 569 /** 570 * @brief expose_widgets - send a expose event (EXPOSE) to a Widget_t 571 * @param w - the Widget_t to send the event to 572 * @return void 573 */ 574 575 void expose_widget(Widget_t *w); 576 577 /** 578 * @brief _key_mapping - modifier key's mapped to a integer value 579 * @param *dpy - pointer to the Display in use 580 * @param *xkey - the key to map 581 * @return int - value (1-10) or 0 when not mapped 582 */ 583 584 int key_mapping(Display *dpy, XKeyEvent *xkey); 585 586 #ifdef __cplusplus 587 } 588 #endif 589 590 #endif //XWIDGET_H 591