1 /* aguix.h 2 * This file belongs to Worker, a file manager for UN*X/X11. 3 * Copyright (C) 2001-2020 Ralf Hoffmann. 4 * You can contact me at: ralf@boomerangsworld.de 5 * or http://www.boomerangsworld.de/worker 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #ifndef AGUIX_H 23 #define AGUIX_H 24 25 #include "aguixdefs.h" 26 #include "lowlevelfunc.h" 27 #include "message.h" 28 #include "util.h" 29 #include "refcount.hh" 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <X11/Xlib.h> 35 #include <X11/Xutil.h> 36 #include <X11/keysym.h> 37 #include <X11/cursorfont.h> 38 #include <X11/Xatom.h> 39 40 #ifdef HAVE_XFT 41 #include <X11/Xft/Xft.h> 42 #endif 43 44 #include <map> 45 #include <list> 46 #include <atomic> 47 #include <memory> 48 49 #include "aguixfont.hh" 50 #include "aguixcolor.hh" 51 #include "backgroundmessagehandler.hh" 52 53 #include "faces.hh" 54 55 class AWindow; 56 class PopUpWindow; 57 class BubbleWindow; 58 class TimeoutStore; 59 60 enum {MES_WAIT,MES_GET}; 61 enum {NON_GADGET,CLOSE_GADGET,BUTTON_GADGET,SHADOW_GADGET,CHOOSE_GADGET,LISTVIEW,ONELVC,MORELVC,STRING_GADGET}; 62 63 struct AGUIX_XProperty { AGUIX_XPropertyAGUIX_XProperty64 AGUIX_XProperty() : success( true ), 65 property_data( NULL ), 66 type( None ), 67 format( 0 ), 68 number_of_items( 0 ) 69 {} 70 freePropertyAGUIX_XProperty71 void freeProperty() 72 { 73 if ( property_data ) { 74 XFree( property_data ); 75 property_data = NULL; 76 } 77 } 78 79 bool success; 80 unsigned char *property_data; 81 Atom type; 82 int format; 83 unsigned long number_of_items; 84 }; 85 86 class AGUIX { 87 public: 88 AGUIX( int argc, char **argv, const std::string &classname ); 89 ~AGUIX(); 90 AGUIX( const AGUIX &other ); 91 AGUIX &operator=( const AGUIX &other ); 92 93 int initX(); 94 int checkX(); 95 void closeX(); 96 int getDepth() const; 97 Colormap getColormap() const; 98 Display *getDisplay() const; 99 int getScreen() const; 100 void panic(const char *); 101 void setFG( const AGUIXColor &color ); 102 void setBG( const AGUIXColor &color ); 103 void setFG( GC gc, const AGUIXColor &color ); 104 void setBG( GC gc, const AGUIXColor &color ); 105 int getCharHeight() const; 106 void FillRectangle(Drawable buffer,int x,int y,int w,int h); 107 void DrawText( class DrawableCont &dc, const char *text, int x, int y, const AGUIXColor &color ); 108 void DrawLine(Drawable buffer,int px1,int py1,int px2,int py2); 109 void DrawPoint(Drawable buffer,int x,int y); 110 void FillRectangle(Drawable buffer,GC gc,int x,int y,int w,int h); 111 void DrawText( class DrawableCont &dc, AGUIXFont *, const char *text, int x, int y, const AGUIXColor &color ); 112 void DrawLine(Drawable buffer,GC gc,int px1,int py1,int px2,int py2); 113 void DrawPoint(Drawable buffer,GC gc,int x,int y); 114 115 void DrawTriangleFilled(Drawable buffer, int px1, int py1, int px2, int py2, int px3, int py3); 116 void DrawTriangleFilled(Drawable buffer, GC tgc, int px1, int py1, int px2, int py2, int px3, int py3); 117 void setClip( AGUIXFont *font, class DrawableCont *dc, int x, int y, int width, int height ); 118 void unclip( AGUIXFont *font, class DrawableCont *dc ); 119 120 void ClearWin(Window win); 121 void SetWindowBG( Window win, const AGUIXColor &color ); 122 int getFontBaseline() const; 123 AGUIXColor AddColor( int red, int green, int blue, AGUIXColor::color_type_t type = AGUIXColor::USER_COLOR ); 124 void freeColors(); 125 int changeColor( const AGUIXColor &index, int red, int green ,int blue ); 126 int getNumberOfColorsForType( AGUIXColor::color_type_t type ) const; 127 unsigned long getPixel( const AGUIXColor &color ) const; 128 #ifdef HAVE_XFT 129 XftColor *getColBufEntry( const AGUIXColor &color ); 130 #else 131 unsigned long getColBufEntry( const AGUIXColor &color ); 132 #endif 133 134 typedef struct _col_values_t { _col_values_t_col_values_t135 _col_values_t() : red( 0 ), 136 green( 0 ), 137 blue( 0 ) 138 {} _col_values_t_col_values_t139 _col_values_t( int r, int g, int b) : red( r ), 140 green( g ), 141 blue( b ) 142 {} 143 144 bool operator==( const _col_values_t &rhs ) 145 { 146 if ( red == rhs.red && 147 green == rhs.green && 148 blue == rhs.blue ) { 149 return true; 150 } else { 151 return false; 152 } 153 } 154 155 int red, green, blue; 156 } col_values_t; 157 158 col_values_t getColorInfo( const AGUIXColor &color ) const; 159 col_values_t blend( const col_values_t &lhs, 160 const col_values_t &rhs, 161 int percentage ) const; 162 163 AGUIXColor getColor( const col_values_t &v ); 164 165 std::string getClassname() const; 166 Atom *getCloseAtom(); 167 void insertWindow( AWindow *win, bool change_transient = false ); 168 void removeWindow(AWindow *win); 169 AGMessage *GetMessage(AWindow *parent); 170 AGMessage *WaitMessage(AWindow *parent); 171 void ReplyMessage(AGMessage *); 172 Message *wait4mess( int mode ); 173 void copyArea(Drawable source,Drawable dest,int s_x,int s_y,int width,int height,int d_x,int d_y); 174 void Flush(); 175 int getargc() const; 176 char **getargv() const; 177 void putAGMsg(AGMessage *msg); 178 AGMessage *getAGMsg(); 179 void WindowtoFront(Window); 180 void WindowtoBack(Window); 181 AGUIXFont *getFont( const char* ); 182 int setFont( const char* ); 183 void ExposeHandler(Message*); 184 AWindow *findAWindow(Window); 185 char *getNameOfKey(KeySym,unsigned int) const; 186 Window getGroupWin() const; 187 int queryPointer(Window win,int *x,int *y); 188 int queryRootPointer(int *x,int *y); 189 int queryPointer(Window win,int *x,int *y,unsigned int *buttons); 190 void setCursor(Window win,int type); 191 void unsetCursor(Window win); 192 193 enum {WAIT_CURSOR=0,SCROLLH_CURSOR,SCROLLV_CURSOR,MAXCURSORS}; 194 int startCut(GUIElement *elem,const char *buffer); 195 void cancelCut(); 196 int startPaste(GUIElement *elem); 197 bool amiOwner() const; 198 const char *getCutBuffer() const; 199 void requestCut( Window win, bool fallback = false ); 200 bool rerequestCut(); 201 void cancelCutPaste(GUIElement *elem); 202 bool isDoubleClick(struct timeval *t1,struct timeval *t2) const; 203 bool isDoubleClick( Time t1, Time t2 ) const; 204 205 static int scaleElementsW( int wantedWidth, 206 int borderwidth, 207 int minSpace, 208 int maxSpace, 209 bool allowShrink, 210 bool allowStretch, 211 GUIElement **elem, 212 int *minWidths, 213 int nr ); 214 static int centerElementsY( GUIElement *element, 215 GUIElement *center2element ); 216 int getRootWindowWidth() const; 217 int getRootWindowHeight() const; 218 219 Pixmap createPixmap( Drawable d, int width, int height ); 220 void freePixmap( Pixmap p ); 221 222 void DrawDottedLine( Drawable buffer, int px1, int py1, int px2, int py2 ); 223 void DrawDottedRectangle( Drawable buffer, int x, int y, int w, int h ); 224 void setDottedFG( const AGUIXColor &color ); 225 226 void DrawDashXorLine( Drawable buffer, int px1, int py1, int px2, int py2 ); 227 void DrawDashXorRectangle( Drawable buffer, int x, int y, int w, int h ); 228 229 void DrawDashDLine( Drawable buffer, int px1, int py1, int px2, int py2 ); 230 void DrawDashDRectangle( Drawable buffer, int x, int y, int w, int h ); 231 void setDashDFG( const AGUIXColor &color ); 232 void setDashDBG( const AGUIXColor &color ); 233 234 static bool isModifier( KeySym key ); 235 static char *getStringForKeySym( KeySym key ); 236 static KeySym getKeySymForString( const char *str1 ); 237 void rebuildBackgroundPixmap(); 238 void setWindowBackgroundPixmap( Window win ); 239 void doXMsgs( AWindow *parent, bool onlyexpose ); 240 void doXMsgs( int mode, AWindow *parent, bool onlyexpose ); 241 bool noMoreMessages() const; 242 #ifdef USE_XIM 243 XIMStyle getXIMStyle() const; 244 XIM getXIM() const; 245 void IMInstCallback( Display *calldsp ); 246 void IMDestCallback(); 247 #endif 248 void setTransientWindow( AWindow *twin = NULL ); 249 const AWindow* getTransientWindow() const; 250 KeySym getLastKeyRelease(); 251 unsigned int getLastMouseRelease(); 252 void msgLock( Widget *e ); 253 void msgUnlock( const Widget *e ); 254 bool msgHoldsLock( const Widget *e ); 255 void enableTimer(); 256 void disableTimer(); 257 258 int getTextWidth( const char *str, AGUIXFont *font = NULL ); 259 int getTextWidth( const char *str, AGUIXFont *font, int len ); 260 int getStrlen4Width( const char *str, int width, int *return_width, AGUIXFont *font = NULL ); 261 262 /** 263 * 264 * @param str 265 * @param maxlen use not more then len bytes (or <0 for strlen) 266 */ 267 int getStrlen4WidthMaxlen( const char *str, int maxlen, 268 int width, int *return_width, AGUIXFont *font = NULL ); 269 270 static std::atomic< long > timerEvent; 271 272 void drawBorder( Drawable buffer, GC usegc, bool pressed, int x, int y, int w, int h, int topright_space ); 273 void drawBorder( Drawable buffer, bool pressed, int x, int y, int w, int h, int topright_space ); 274 275 typedef enum { CLOSE_ATOM, NET_WM_NAME_ATOM, NET_WM_ICON_NAME_ATOM, TARGETS_ATOM, 276 NET_WM_WINDOW_TYPE, NET_WM_WINDOW_TYPE_DIALOG, NET_WM_WINDOW_TYPE_NORMAL, 277 UTF8_STRING, NET_WM_STATE, NET_WM_STATE_MAXIMIZED_HORZ, 278 NET_WM_STATE_MAXIMIZED_VERT, 279 XDNDENTER, 280 XDNDPOSITION, 281 XDNDSTATUS, 282 XDNDTYPELIST, 283 XDNDACTIONCOPY, 284 XDNDDROP, 285 XDNDLEAVE, 286 XDNDFINISHED, 287 XDNDSELECTION, 288 XDNDPROXY, 289 XDNDAWARE, 290 CARDINAL_ATOM, 291 NET_WM_ICON_ATOM 292 } atom_name_t; 293 Atom getAtom( atom_name_t name ) const; 294 295 void registerPopUpWindow( PopUpWindow *win ); 296 void hidePopUpWindows( int group_id = -1 ); 297 void hideOtherPopUpWindows( int group_id = -1 ); 298 void popupOpened(); 299 void popupClosed(); 300 301 void xSync(); 302 303 int getWidgetRootPosition( Widget *widget, int *x, int *y ); 304 bool getLastTypedWindowEvent( Window win, int type, XEvent *return_event ); 305 int addDefaultColors(); 306 307 AWindow *getFocusedAWindow(); 308 309 void registerBGHandler( AWindow *window, const RefCount< BackgroundMessageHandler > &handler ); 310 void unregisterBGHandler( AWindow *window ); 311 void executeBGHandlers( AGMessage &msg ); 312 void destroyBGHandlers(); 313 314 void copyToClipboard( const std::string &s ); 315 316 /** 317 * return the location and dimension of the largest (xinerama) screen 318 * under the mouse 319 */ 320 void getLargestDimensionOfCurrentScreen( int *x, int *y, 321 int *width, int *height ); 322 323 void setApplyWindowDialogType( bool nv ); 324 bool getApplyWindowDialogType() const; 325 326 void setOverrideXIM( bool nv ); 327 bool getOverrideXIM() const; 328 329 void setSkipFilterEvent( bool nv ); 330 331 void applyFaces( const FaceDB &faces ); getFaces()332 const FaceDB &getFaces() const 333 { 334 return m_faces; 335 } 336 getFaceCol_default_fg()337 int getFaceCol_default_fg() const 338 { 339 return m_default_fg; 340 } 341 getFaceCol_default_bg()342 int getFaceCol_default_bg() const 343 { 344 return m_default_bg; 345 } 346 getFaceCol_3d_bright()347 int getFaceCol_3d_bright() const 348 { 349 return m_3d_bright; 350 } 351 getFaceCol_3d_dark()352 int getFaceCol_3d_dark() const 353 { 354 return m_3d_dark; 355 } 356 357 void setBubbleHelpWindow( std::shared_ptr< BubbleWindow > bw ); 358 void setBubbleHelpCandidate( GUIElement *elem ); 359 void clearBubbleHelpCandidate( GUIElement *elem = NULL); 360 361 void setExternalTimeoutStore( std::weak_ptr< TimeoutStore > timeout_store ); 362 363 void external_timeout_callback(); 364 365 bool isValidScreenPosition( int x, int y, 366 int w, int h ); 367 368 void startXDND( Widget *initiator, 369 Window w, 370 unsigned int mouse_button ); 371 372 void widgetDestroyed( Widget *w ); 373 374 int getCurrentUserColorInstance() const; 375 376 bool isModifierPressed( unsigned int mask ); 377 378 void setStandardIconData( const unsigned long *data, 379 size_t data_length ); 380 bool getStandardIconData( const unsigned long **return_data, 381 size_t *return_data_length ) const; 382 private: 383 Display *dsp; 384 int scr; 385 Colormap cmap; 386 GC gc, dotted_gc, dashxor_gc, dashdouble_gc; 387 Atom WM_delete_window, 388 XA_NET_WM_NAME, 389 XA_NET_WM_ICON_NAME, 390 XA_TARGETS, 391 XA_NET_WM_WINDOW_TYPE, 392 XA_NET_WM_WINDOW_TYPE_DIALOG, 393 XA_NET_WM_WINDOW_TYPE_NORMAL, 394 XA_UTF8_STRING, 395 XA_NET_WM_STATE, 396 XA_NET_WM_STATE_MAXIMIZED_HORZ, 397 XA_NET_WM_STATE_MAXIMIZED_VERT, 398 XA_XDNDENTER, 399 XA_XDNDPOSITION, 400 XA_XDNDSTATUS, 401 XA_XDNDTYPELIST, 402 XA_XDNDACTIONCOPY, 403 XA_XDNDDROP, 404 XA_XDNDLEAVE, 405 XA_XDNDFINISHED, 406 XA_XDNDSELECTION, 407 XA_XDNDPROXY, 408 XA_XDNDAWARE, 409 XA_MULTIPLE, 410 XA_TEXT_URI_LIST, 411 XA_TEXT_PLAIN, 412 XA_NET_WM_ICON, 413 XA_CARDINAL_ATOM; 414 415 int m_argc; 416 char **m_argv; 417 std::string m_classname; 418 unsigned long white,black; 419 AGUIXFont *mainfont; 420 int initOK; 421 int CharHeight; 422 #ifdef HAVE_XFT 423 XftColor m_user_col_buf[256]; 424 XftColor m_system_col_buf[16]; 425 std::vector< XftColor > m_extra_col_buf; 426 #else 427 unsigned long m_user_col_buf[256]; 428 unsigned long m_system_col_buf[16]; 429 std::vector< unsigned long > m_extra_col_buf; 430 #endif 431 int m_user_colors, m_system_colors, m_extra_colors; 432 433 std::map< AGUIXColor, col_values_t, AGUIXColor::compare_func > m_color_values; 434 435 XEvent LastEvent; 436 std::list<AWindow*> wins; 437 typedef std::list<AWindow*>::const_iterator wins_cit_t; 438 typedef std::list<AWindow*>::iterator wins_it_t; 439 440 std::list<AGMessage*> messages; 441 typedef std::list<AGMessage*>::const_iterator agmessage_list_cit_t; 442 typedef std::list<AGMessage*>::iterator agmessage_list_it_t; 443 444 std::list<AGUIXFont*> fonts; 445 typedef std::list<AGUIXFont*>::const_iterator aguixfont_list_cit_t; 446 typedef std::list<AGUIXFont*>::iterator aguixfont_list_it_t; 447 448 std::list<PopUpWindow*> popup_wins; 449 typedef std::list<PopUpWindow*>::const_iterator popup_wins_cit_t; 450 typedef std::list<PopUpWindow*>::iterator popup_wins_it_t; 451 452 std::list<AWindow*> wins_as_transient_for; 453 454 Window groupwin; 455 void createGroupWin(); 456 void destroyGroupWin(); 457 458 bool ReactMessage(Message*,AWindow*); 459 void buildAGMessage( Message *agmsg ); 460 461 bool privatecmap; 462 void changeColormap(); 463 void updateSystemColors( int changed_user_color ); 464 465 Cursor cursors[MAXCURSORS]; 466 GUIElement *cutstart,*pastestart; 467 468 unsigned int rootWindowWidth, rootWindowHeight; 469 Pixmap backpm; 470 #ifdef USE_XIM 471 XIM inputmethod; 472 XIMStyle im_style; 473 474 int openIM(); 475 void closeIM(); 476 #endif 477 char *keybuf; 478 int keybuf_len; 479 480 AWindow *transientwindow; 481 KeySym lastkeyrelease; 482 unsigned int lastmouserelease; 483 484 Widget *msgLockElement; 485 bool timerEnabled; 486 #ifndef USE_AGUIXTIMER 487 struct timeval timerStart; 488 #endif 489 int msgHandler( int mode, AWindow *parent, bool onlyExpose ); 490 enum { TIMER_TICKS = 25 }; //HARDCODED 491 long lastTimerEventNr; 492 493 void checkPopUpWindows( Message * ); 494 495 bool waitForEventOnFD( int ms ); 496 497 AGUIX_XProperty getProperty( Window win, 498 Atom property ); 499 Atom selectBestTargetForDND( Atom type1, 500 Atom type2, 501 Atom type3 ); 502 Atom selectBestTargetForDND( AGUIX_XProperty type_list ); 503 Atom selectBestTargetForDND( const std::vector< Atom > &list ); 504 505 void handleXDNDEnter( XEvent *e ); 506 void handleXDNDPosition( XEvent *e ); 507 void handleXDNDLeave( XEvent *e ); 508 void handleXDNDDrop( XEvent *e ); 509 void handleXDNDStatus( XEvent *e ); 510 void handleXDNDFinished( XEvent *e ); 511 void cleanupDND(); 512 513 void initXDNDTypes(); 514 515 void processSelectionRequest( XEvent *e ); 516 void setTargetsProperty( Window w, Atom property ); 517 Window findXDNDAwareWindow( Window w, Window *return_proxy_window ); 518 519 int m_open_popup_counter; 520 bool m_popup_ignore_button_release; 521 522 Window m_current_xfocus_window; 523 524 /* background handler for some window */ 525 std::map< AWindow *, RefCount< BackgroundMessageHandler > > m_bg_handlers; 526 527 /* temporary list for unregister to cleanup handler after execution */ 528 std::list< RefCount< BackgroundMessageHandler > > m_bg_handler_cleanup_list; 529 std::list< AWindow *> m_bg_handler_erase_handler; 530 531 std::string clipboard_string; 532 533 Atom m_last_selection_request_atom; 534 Window m_last_selection_request_window; 535 536 bool m_apply_window_dialog_type; 537 538 bool m_override_xim; 539 bool m_skip_filter_event; 540 541 int m_filtered_key_events_in_a_row; 542 543 FaceDB m_faces; 544 545 int m_default_fg; 546 int m_default_bg; 547 int m_3d_bright; 548 int m_3d_dark; 549 550 struct bubble_help_data { bubble_help_databubble_help_data551 bubble_help_data() : help_candidate( NULL ), 552 enter_time{ 0, 0 } 553 {} 554 std::shared_ptr< BubbleWindow > bubble_help_window; 555 GUIElement *help_candidate; 556 struct timeval enter_time; 557 } m_bubble_help; 558 559 time_t now; 560 561 struct aguix_timeouts { aguix_timeoutsaguix_timeouts562 aguix_timeouts() : timeout_set( false ) 563 {} 564 ~aguix_timeoutsaguix_timeouts565 ~aguix_timeouts() 566 { 567 disableExternalTimer(); 568 } 569 570 std::weak_ptr< TimeoutStore > timeout_store; 571 bool timeout_set; 572 573 void enableExternalTimer(); 574 void disableExternalTimer(); 575 } m_external_timeouts; 576 577 struct aguix_xdnd_state { aguix_xdnd_stateaguix_xdnd_state578 aguix_xdnd_state() : drop_active( false ), 579 source( None ), 580 selected_target( None ), 581 last_activity( 0 ), 582 version( 0 ), 583 target_awin( NULL ), 584 sent_target_request( false ), 585 target_widget( NULL ), 586 drag_active( false ), 587 drag_target_status( AGUIX_XDND_UNAWARE ), 588 drag_initiator( NULL ), 589 drag_initiator_window( None ), 590 drag_current_target_window( None ), 591 drag_current_target_version( -1 ), 592 drag_current_proxy_target_window( None ), 593 drag_selection_pending( false ), 594 drop_issued( false ), 595 mouse_button( Button1 ), 596 position_silent( false ), 597 position_silent_x( 0 ), 598 position_silent_y( 0 ), 599 position_silent_w( 0 ), 600 position_silent_h( 0 ) 601 {} 602 603 enum xdnd_target_status { 604 AGUIX_XDND_UNAWARE, 605 AGUIX_XDND_UNRESPONSIVE, 606 AGUIX_XDND_ACCEPT 607 }; 608 609 bool drop_active; 610 Window source; 611 Atom selected_target; 612 time_t last_activity; 613 int version; 614 AWindow *target_awin; 615 bool sent_target_request; 616 Widget *target_widget; 617 618 bool drag_active; 619 enum xdnd_target_status drag_target_status; 620 Widget *drag_initiator; 621 Window drag_initiator_window; 622 Window drag_current_target_window; 623 int drag_current_target_version; 624 625 Window drag_current_proxy_target_window; 626 627 bool drag_selection_pending; 628 bool drop_issued; 629 630 unsigned int mouse_button; 631 632 bool position_silent; 633 int position_silent_x; 634 int position_silent_y; 635 int position_silent_w; 636 int position_silent_h; 637 } m_xdnd; 638 639 std::map< std::string, int > m_xdnd_receive_types; 640 641 Cursor m_xcursor_plus; 642 Cursor m_xcursor_circle; 643 644 int m_x_fd; 645 646 int m_user_color_instance; 647 648 unsigned int m_modifier_pressed = 0; 649 650 const unsigned long *m_net_wm_icon_data = NULL; 651 size_t m_net_wm_icon_data_length = 0; 652 }; 653 654 #endif 655 656 /* Local Variables: */ 657 /* mode:c++ */ 658 /* End: */ 659