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 has fixed size */ 169 FIXEDSIZE , 170 /** Widget_t adjust in a aspect frame */ 171 MENUITEM , 172 /** Widget_t request no adjustment in frame */ 173 NONE , 174 }Gravity; 175 176 /** 177 * 178 * @brief Resize_t - struct used to resize child widgets 179 * @param init_x - initial x position on Parent 180 * @param init_y - initial y position on Parent 181 * @param init_width - initial width 182 * @param init_height - initial height 183 * @param scale_x - scalling size of the x axsis 184 * @param scale_y - scalling size of the y axsis 185 * @param cscale_x - scalling factor of the x axsis 186 * @param cscale_y - scalling factor of the y axsis 187 * @param ascale - scalling factor for aspect scalling 188 */ 189 190 typedef struct { 191 /** indicate how the widget wish to be resized */ 192 Gravity gravity; 193 /** initial x position on Parent */ 194 int init_x; 195 /** initial y position on Parent */ 196 int init_y; 197 /** initial width */ 198 int init_width; 199 /** initial height */ 200 int init_height; 201 /** scalling size of the x axsis */ 202 float scale_x; 203 /** scalling size of the y axsis */ 204 float scale_y; 205 /** scalling factor of the x axsis */ 206 float cscale_x; 207 /** scalling factor of the y axsis */ 208 float cscale_y; 209 /** rescalling factor of the x axsis */ 210 float rcscale_x; 211 /** rescalling factor of the y axsis */ 212 float rcscale_y; 213 /** scalling factor for aspect scalling */ 214 float ascale; 215 } Resize_t; 216 217 /** 218 * 219 * @brief anonymous enum - flags to set Widget_t properties 220 * @param IS_WIDGET - Widget_t is a sub widget 221 * @param IS_WINDOW - Widget_t has no Widget_t parent 222 * @param IS_POPUP - Widget_t is a pop up widget 223 * @param IS_RADIO - Widget_t is part of a radio group 224 * @param USE_TRANSPARENCY - Widget_t need transparent draw (buffer) 225 * @param HAS_FOCUS - Mouse pointer is above Widget_t 226 * @param HAS_POINTER - Mouse pointer is pressed on Widget_t 227 * @param HAS_TOOLTIP - Widget_t have tooltip 228 * @param HAS_MEM - Widget_t have mem to be released 229 */ 230 231 enum { 232 /** Widget_t is a sub widget */ 233 IS_WIDGET = 1<<0, 234 /** Widget_t has no Widget_t parent */ 235 IS_WINDOW = 1<<1, 236 /** Widget_t is a pop up widget */ 237 IS_POPUP = 1<<2, 238 /** Widget_t is part of a radio group */ 239 IS_RADIO = 1<<3, 240 /** Widget_t is a tooltip widget */ 241 IS_TOOLTIP = 1<<4, 242 /** Widget_t need transparent draw (buffer) */ 243 USE_TRANSPARENCY = 1<<5, 244 /** Mouse pointer is above Widget_t */ 245 HAS_FOCUS = 1<<6, 246 /** Mouse pointer is pressed on Widget_t */ 247 HAS_POINTER = 1<<7, 248 /** Widget_t have tooltip */ 249 HAS_TOOLTIP = 1<<8, 250 /** Widget_t have mem to be released */ 251 HAS_MEM = 1<<9, 252 /** Widget_t didn't receive autorepeated keys */ 253 NO_AUTOREPEAT = 1<<10, 254 /** Widget_t need fast redrawing */ 255 FAST_REDRAW = 1<<11, 256 /** Hide Widget_t instead delete on "WM_DELETE_WINDOW" */ 257 HIDE_ON_DELETE = 1<<12, 258 /** Widget_t reuse a surface from a other Widget_t */ 259 REUSE_IMAGE = 1<<13, 260 }; 261 262 /** 263 * 264 * @brief Widget_t - struct to hold the basic Widget_t info 265 * @param *app - pointer to the main struct 266 * @param widget - the X11 Window 267 * @param *parent - pointer to the Parent Window or Widget_t 268 * @param event_callback - the main XEvent callback 269 * @param func - struct holding the event callbacks 270 * @param *surface - pointer to the cairo xlib surface 271 * @param *cr - pointer to the cairo xlib surface context 272 * @param *buffer - pointer to the cairo buffer surface 273 * @param *crb - pointer to the cairo buffer surface context 274 * @param *image - pointer to the cairo image surface 275 * @param data - int to hold user data 276 * @param flags - unsigned int to hold Widget_t flags 277 * @param *label - pointer to the widget label 278 * @param input_label - char array the widget input label 279 * @param state - int to hold the widget state 280 * @param pos_x - mouse pointer x position on button press 281 * @param pos_y - mouse pointer y position on button press 282 * @param x - x position of Window on Parent 283 * @param y - y position of Window on Parent 284 * @param width - widget width 285 * @param height - widget height 286 * @param scale - struct used to resize child widgets 287 * @param *adj_x - pointer to the x axis adjustment 288 * @param *adj_y - pointer to the y axis adjustment 289 * @param *adj - pointer to the adjustment in use 290 * @param *childlist - pointer to Widget_t child list 291 * @param xic - Locale and UTF 8 support interface 292 * @param xim - Context to Locale and UTF 8 support 293 */ 294 295 struct Widget_t { 296 /** pointer to the main struct */ 297 Xputty *app; 298 /** the X11 newly created Window */ 299 Window widget; 300 /** pointer to the Parent Window or Widget_t */ 301 void *parent; 302 /** pointer to the Parent struct */ 303 void *parent_struct; 304 /** the main XEvent callback */ 305 vfunc event_callback; 306 /** struct holding the event callbacks */ 307 Func_t func; 308 /** pointer to the cairo xlib surface */ 309 cairo_surface_t *surface; 310 /** pointer to the cairo xlib surface context */ 311 cairo_t *cr; 312 /** pointer to the cairo buffer surface used for transparency */ 313 cairo_surface_t *buffer; 314 /** pointer to the cairo buffer surface context */ 315 cairo_t *crb; 316 /** pointer to the cairo image surface used to load a png */ 317 cairo_surface_t *image; 318 /** int to hold user data */ 319 int data; 320 /** int to hold Widget_t flags */ 321 long int flags; 322 /** pointer to the widget label */ 323 const char* label; 324 /** char array to hold user input */ 325 char input_label[32]; 326 /** pointer to the x axis adjustment */ 327 Adjustment_t *adj_x; 328 /** pointer to the y axis adjustment */ 329 Adjustment_t *adj_y; 330 /** pointer to the adjustment in use*/ 331 Adjustment_t *adj; 332 /** pointer to Widget_t child list */ 333 Childlist_t *childlist; 334 /** Locale and UTF 8 support */ 335 XIC xic; 336 /** Context to Locale and UTF 8 support */ 337 XIM xim; 338 /** int to hold the widget state default = 0 */ 339 int state; 340 /** mouse pointer x position on button press */ 341 int pos_x; 342 /** mouse pointer y position on button press */ 343 int pos_y; 344 /** x position of Window related to the Parent */ 345 int x; 346 /** y position of Window related to the Parent */ 347 int y; 348 /** the widget size x-axis */ 349 int width; 350 /** the widget size y-axis */ 351 int height; 352 /** struct used to resize child widgets */ 353 Resize_t scale; 354 }; 355 356 357 /** 358 * @brief *create_window - create a Window 359 * \n You need to create as least minimum one Window to get started. 360 * \n The first created Window is the top_level_widget() 361 * \n A Window could be created on the DefaultRootWindow() or embeded 362 * into a other XWindow 363 * @param *app - pointer to the Xputty *main struct to use 364 * @param win - pointer to the Parent Window (may be Root) 365 * @param x,y,width,height - the position/geometry to create the window 366 * @return Widget_t * - pointer to the Widget_t struct 367 */ 368 369 Widget_t *create_window(Xputty *app, Window win, 370 int x, int y, int width, int height); 371 372 /** 373 * @brief *create_widget - create a widget 374 * \n A Widget_t could only be created as child of a other Widget_t 375 * \n To create a Widget_t you need to create a Widget_t with create_window() 376 * before. 377 * @param *app - pointer to the Xputty *main struct to use 378 * @param *parent - pointer to the Parent Widget_t 379 * @param x,y,width,height - the position/geometry to create the widget 380 * @return Widget_t* - pointer to the Widget_t struct 381 */ 382 383 Widget_t *create_widget(Xputty *app, Widget_t *win, 384 int x, int y, int width, int height); 385 386 /** 387 * @brief connect_func - connect a event with a handler 388 * without type check. For supported events see: Func_t 389 * @param **event - the event to connect 390 * @param *handler - the handler to handle the event 391 * @return void 392 */ 393 394 void connect_func(void (**event)(), void (*handler)()); 395 396 /** 397 * @brief widget_set_title - set window title for a Widget_t 398 * @param *w - pointer to the Widget_t to set the title 399 * @param *title - the title to store 400 * @return void 401 */ 402 403 void widget_set_title(Widget_t *w, const char *title); 404 405 /** 406 * @brief widget_show - map/show widget 407 * @param *w - pointer to the Widget_t to map 408 * @return void 409 */ 410 411 void widget_show(Widget_t *w); 412 413 /** 414 * @brief pop_widget_show_all - map/show popup widget with all it's childs 415 * @param *w - pointer to the Widget_t to map 416 * @return void 417 */ 418 419 void pop_widget_show_all(Widget_t *w); 420 421 /** 422 * @brief widget_hide - unmap/hide a Widget_t 423 * @param *w - pointer to the Widget_t to unmap 424 * @return void 425 */ 426 427 void widget_hide(Widget_t *w); 428 429 /** 430 * @brief widget_show_all - map/show Widget_t with all childs 431 * @param *w - pointer to the Widget_t to map 432 * @return void 433 */ 434 435 void widget_show_all(Widget_t *w); 436 437 /** 438 * @brief show_tooltip - check if a Widget_t have a tooltip, 439 * and show it, if a tooltip is available. 440 * @param *wid - pointer to the Widget_t receiving the event 441 * @return void 442 */ 443 444 void show_tooltip(Widget_t *wid); 445 446 /** 447 * @brief hide_tooltip - check if a Widget_t have a tooltip, 448 * and hide it, if a tooltip is mapped. 449 * @param *wid - pointer to the Widget_t receiving the event 450 * @return void 451 */ 452 453 void hide_tooltip(Widget_t *wid); 454 455 /** 456 * @brief *get_toplevel_widget - get pointer to the top level Widget_t 457 * @param *main - pointer to the main Xputty struct 458 * @return void 459 */ 460 461 Widget_t *get_toplevel_widget(Xputty *main); 462 463 /** 464 * @brief quit - exit the main loop 465 * @param *w - pointer to the Widget_t sending the request 466 * @return void 467 */ 468 469 void quit(Widget_t *w); 470 471 /** 472 * @brief quit_widget - remove a widget from the processing loop 473 * @param *w - pointer to the Widget_t sending the request 474 * @return void 475 */ 476 477 void quit_widget(Widget_t *w); 478 479 /** 480 * @brief transparent_draw - copy parent surface to child surface 481 * \n you usaualy didn't need to call this, it's used automatically 482 * when a Widget_t have set the flag USE_TRANSPARENCY 483 * \n this is the default setting for Widget_t 484 * @param *wid - pointer to the Widget_t receiving the event 485 * @param *user_data - void pointer to attached user_data 486 * @return void 487 */ 488 489 void transparent_draw(void * wid, void* user_data); 490 491 /** 492 * @brief widget_reset_scale - used to reset scaling mode after a image surface 493 * is drawn to the Widget_t surface with widget_set_scale() 494 * @param *w - pointer to the Widget_t sending the request 495 * @return void 496 */ 497 498 void widget_reset_scale(Widget_t *w); 499 500 /** 501 * @brief widget_set_scale - set scaling mode to scale a image surface 502 * to the size of the Widget_t surface 503 * @param *w - pointer to the Widget_t sending the request 504 * @return void 505 */ 506 507 void widget_set_scale(Widget_t *w); 508 509 /** 510 * @brief destroy_widget - destroy a widget 511 * \n When a Widget_t receive a destroy_widget() call, it will propagate that 512 * to all childs in it's Childlist_t. So all childs get destroyed before the 513 * Widget_t itself close. 514 * @param *w - pointer to the Widget_t sending the request 515 * @param *main - pointer to main struct 516 * @return void 517 */ 518 519 void destroy_widget(Widget_t *w, Xputty *main); 520 521 /** 522 * @brief widget_event_loop - the internal widget event loop 523 * @param *w - void pointer to the Widget_t receiving the event 524 * @param *event - void pointer to the XEvent 525 * @param *main - void pointer to the Xputty *main struct running 526 * the event loop 527 * @param *user_data - void pointer to attached user_data 528 * @return void 529 */ 530 531 void widget_event_loop(void *w_, void* event, Xputty *main, void* user_data); 532 533 /** 534 * @brief send_configure_event - send a ConfigureNotify to Widget_t 535 * \n used to resize a Widget_t 536 * @param *w - pointer to the Widget_t to send the notify 537 * @param x,y - the new Widget_t position 538 * @param width,height - the new Widget_t size 539 * @return void 540 */ 541 542 void send_configure_event(Widget_t *w,int x, int y, int width, int height); 543 544 /** 545 * @brief send_button_press_event - send ButtonPress event to Widget_t 546 * \n simulate a BUTTON_PRESS Event 547 * @param *w - pointer to the Widget_t to send the notify 548 * @return void 549 */ 550 551 void send_button_press_event(Widget_t *w); 552 553 /** 554 * @brief send_button_release_event - send ButtonRelease event to Widget_t 555 * \n simulate a BUTTON_RELEASE Event 556 * @param *w - pointer to the Widget_t to send the notify 557 * @return void 558 */ 559 560 void send_button_release_event(Widget_t *w); 561 562 /** 563 * @brief send_systray_message - request a systray icon for Widget_t 564 * \n currently not working 565 * @param *w - pointer to the Widget_t to send the notify 566 * @return void 567 */ 568 569 void send_systray_message(Widget_t *w); 570 571 /** 572 * @brief expose_widgets - send a expose event (EXPOSE) to a Widget_t 573 * @param w - the Widget_t to send the event to 574 * @return void 575 */ 576 577 void expose_widget(Widget_t *w); 578 579 /** 580 * @brief _key_mapping - modifier key's mapped to a integer value 581 * @param *dpy - pointer to the Display in use 582 * @param *xkey - the key to map 583 * @return int - value (1-10) or 0 when not mapped 584 */ 585 586 int key_mapping(Display *dpy, XKeyEvent *xkey); 587 588 #ifdef __cplusplus 589 } 590 #endif 591 592 #endif //XWIDGET_H 593