From ead9c2ce24c88523ebe9295015f993231a61b66a Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Sun, 12 Apr 2009 20:00:45 +0000 Subject: [PATCH] Avoiding crashes for recrsive common dialogs (this does not fix the issue at hand yet) (STR #1986, 2150) / Added menu shortcut alignment for OS X / Fixed bad system menu hadling in OS X (STR #2153) / Fixed File Input mouse pointer dragging (STR #2181) git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6757 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- CHANGES | 5 +++++ FL/fl_draw.H | 1 + src/Fl_File_Input.cxx | 10 ++++++---- src/Fl_Menu.cxx | 15 ++++++++++++--- src/Fl_mac.cxx | 12 +++++++++--- src/fl_ask.cxx | 41 +++++++++++++++++++++++++++++++++++------ src/fl_shortcut.cxx | 36 +++++++++++++++++++++++++++++++++--- 7 files changed, 101 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index 7936508e7..cc1491aac 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ CHANGES IN FLTK 1.3.0 + - Avoiding crashes for recursive common dialogs (this does not + fix the issue at hand yet) (STR #1986, 2150) + - Added menu shortcut alignment for OS X + - Fixed bad system menu hadling in OS X (STR #2153) + - Fixed File Input mouse pointer dragging (STR #2181) - Added alternative text input awareness on OS X - Fixed 'del' keycode on OS X (must be verified for all keyboards) - Fixed OS X support for sending and receiving dnd data as utf8 diff --git a/FL/fl_draw.H b/FL/fl_draw.H index aa73ecfa1..5ec841200 100644 --- a/FL/fl_draw.H +++ b/FL/fl_draw.H @@ -436,6 +436,7 @@ FL_EXPORT int fl_measure_pixmap(const char* const* cdata, int &w, int &h); FL_EXPORT void fl_scroll(int X, int Y, int W, int H, int dx, int dy, void (*draw_area)(void*, int,int,int,int), void* data); FL_EXPORT const char* fl_shortcut_label(int shortcut); +FL_EXPORT const char* fl_shortcut_label(int shortcuti, const char **eom); FL_EXPORT void fl_overlay_rect(int x,int y,int w,int h); FL_EXPORT void fl_overlay_clear(); FL_EXPORT void fl_cursor(Fl_Cursor, Fl_Color fg=FL_BLACK, Fl_Color bg=FL_WHITE); diff --git a/src/Fl_File_Input.cxx b/src/Fl_File_Input.cxx index 8760e3436..5f329904d 100644 --- a/src/Fl_File_Input.cxx +++ b/src/Fl_File_Input.cxx @@ -191,6 +191,7 @@ int // O - TRUE if we handled event Fl_File_Input::handle(int event) // I - Event { // printf("handle(event = %d)\n", event); + static char inButtonBar = 0; switch (event) { case FL_MOVE : @@ -203,18 +204,19 @@ Fl_File_Input::handle(int event) // I - Event return 1; case FL_PUSH : + inButtonBar = (Fl::event_y() < (y() + DIR_HEIGHT)); case FL_RELEASE : case FL_DRAG : - if (Fl::event_y() < (y() + DIR_HEIGHT) || pressed_ >= 0) return handle_button(event); - - return Fl_Input::handle(event); + if (inButtonBar) + return handle_button(event); + else + return Fl_Input::handle(event); default : if (Fl_Input::handle(event)) { damage(FL_DAMAGE_BAR); return 1; } - return 0; } } diff --git a/src/Fl_Menu.cxx b/src/Fl_Menu.cxx index 4ccc35093..1eba33867 100644 --- a/src/Fl_Menu.cxx +++ b/src/Fl_Menu.cxx @@ -106,6 +106,7 @@ public: int numitems; int selected; int drawn_selected; // last redraw has this selected + int shortcutWidth; const Fl_Menu_Item* menu; menuwindow(const Fl_Menu_Item* m, int X, int Y, int W, int H, const Fl_Menu_Item* picked, const Fl_Menu_Item* title, @@ -316,6 +317,7 @@ menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp, itemheight = 1; int hotKeysw = 0; + int hotModsw = 0; int Wtitle = 0; int Htitle = 0; if (t) Wtitle = t->measure(&Htitle, button) + 12; @@ -327,14 +329,18 @@ menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp, if (m->flags&(FL_SUBMENU|FL_SUBMENU_POINTER)) w1 += 14; if (w1 > W) W = w1; if (m->shortcut_) { - w1 = int(fl_width(fl_shortcut_label(m->shortcut_))) + 8; + const char *k, *s = fl_shortcut_label(m->shortcut_, &k); + w1 = int(fl_width(s, k-s)); + if (w1 > hotModsw) hotModsw = w1; + w1 = int(fl_width(k))+4; if (w1 > hotKeysw) hotKeysw = w1; } if (m->labelcolor_ || Fl::scheme() || m->labeltype_ > FL_NO_LABEL) clear_overlay(); } + shortcutWidth = hotKeysw; if (selected >= 0 && !Wp) X -= W/2; int BW = Fl::box_dx(box()); - W += hotKeysw+2*BW+7; + W += hotKeysw+hotModsw+2*BW+7; if (Wp > W) W = Wp; if (Wtitle > W) W = Wtitle; @@ -437,7 +443,10 @@ void menuwindow::drawentry(const Fl_Menu_Item* m, int n, int eraseit) { button ? button->textfont() : FL_HELVETICA; fl_font(f, m->labelsize_ ? m->labelsize_ : button ? button->textsize() : FL_NORMAL_SIZE); - fl_draw(fl_shortcut_label(m->shortcut_), xx, yy, ww-3, hh, FL_ALIGN_RIGHT); + const char *k, *s = fl_shortcut_label(m->shortcut_, &k); + char buf[32]; strcpy(buf, s); buf[k-s] = 0; + fl_draw(buf, xx, yy, ww-shortcutWidth, hh, FL_ALIGN_RIGHT); + fl_draw( k, xx+ww-shortcutWidth, yy, shortcutWidth, hh, FL_ALIGN_LEFT); } if (m->flags & FL_MENU_DIVIDER) { diff --git a/src/Fl_mac.cxx b/src/Fl_mac.cxx index a7835881a..69217df1e 100644 --- a/src/Fl_mac.cxx +++ b/src/Fl_mac.cxx @@ -566,8 +566,11 @@ static pascal OSStatus carbonDispatchHandler( EventHandlerCallRef nextHandler, E switch (GetEventKind( event ) ) { case kEventCommandProcess: - GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd ); - ret = HandleMenu( &cmd ); + ret = GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd ); + if (ret == noErr && (cmd.attributes & kHICommandFromMenu) != 0) + ret = HandleMenu( &cmd ); + else + ret = eventNotHandledErr; break; } break; @@ -1241,7 +1244,7 @@ pascal OSStatus carbonTextHandler( Fl_Window *window = (Fl_Window*)userData; Fl::first_window(window); fl_lock_function(); - int kind = GetEventKind(event); + //int kind = GetEventKind(event); unsigned short buf[200]; ByteCount size; GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, @@ -1259,6 +1262,9 @@ pascal OSStatus carbonTextHandler( fl_lock_function(); Fl::handle(FL_KEYUP, window); fl_unlock_function(); + // for some reason, the window does not redraw until the next mouse move or button push + // sending a 'redraw()' or 'awake()' does not solve the issue! + Fl::flush(); return noErr; } diff --git a/src/fl_ask.cxx b/src/fl_ask.cxx index 6dd1b7a4c..bc69ca57c 100644 --- a/src/fl_ask.cxx +++ b/src/fl_ask.cxx @@ -176,12 +176,15 @@ static int innards(const char* fmt, va_list ap, const char *b1, const char *b2) { + static char avoidRecursion = 0; + if (avoidRecursion) return -1; + avoidRecursion = 1; + makeform(); char buffer[1024]; if (!strcmp(fmt,"%s")) { message->label(va_arg(ap, const char*)); } else { - //: matt: MacOS provides two equally named vsnprintf's... ::vsnprintf(buffer, 1024, fmt, ap); message->label(buffer); } @@ -225,6 +228,8 @@ static int innards(const char* fmt, va_list ap, Fl::grab(g); message_form->hide(); icon->label(prev_icon_label); + + avoidRecursion = 0; return r; } @@ -288,7 +293,11 @@ void fl_beep(int type) { } #endif // WIN32 } -/** Shows an information message dialog box +/** Shows an information message dialog box. + + \note Common dialog boxes are application modal. No more than one common dialog box + can be open at any time. Request for additional dialog boxes are ignored. + \param[in] fmt can be used as an sprintf-like format and variables for the message text */ void fl_message(const char *fmt, ...) { @@ -304,6 +313,10 @@ void fl_message(const char *fmt, ...) { } /** Shows an alert message dialog box + + \note Common dialog boxes are application modal. No more than one common dialog box + can be open at any time. Request for additional dialog boxes are ignored. + \param[in] fmt can be used as an sprintf-like format and variables for the message text */ void fl_alert(const char *fmt, ...) { @@ -319,8 +332,12 @@ void fl_alert(const char *fmt, ...) { } /** Shows a dialog displaying the \p fmt message, this dialog features 2 yes/no buttons + + \note Common dialog boxes are application modal. No more than one common dialog box + can be open at any time. Request for additional dialog boxes are ignored. + \param[in] fmt can be used as an sprintf-like format and variables for the message text - \retval 0 if the no button is selected + \retval 0 if the no button is selected or another dialog box is still open \retval 1 if yes is selected */ int fl_ask(const char *fmt, ...) { @@ -337,11 +354,15 @@ int fl_ask(const char *fmt, ...) { /** Shows a dialog displaying the \p fmt message, this dialog features up to 3 customizable choice buttons + + \note Common dialog boxes are application modal. No more than one common dialog box + can be open at any time. Request for additional dialog boxes are ignored. + \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] b0 text label of button 0 \param[in] b1 text label of button 1 \param[in] b2 text label of button 2 - \retval 0 if the first button with \p b0 text is selected + \retval 0 if the first button with \p b0 text is selected or another dialog box is still open \retval 1 if the second button with \p b1 text is selected \retval 2 if the third button with \p b2 text is selected */ @@ -377,9 +398,13 @@ static const char* input_innards(const char* fmt, va_list ap, } /** Shows an input dialog displaying the \p fmt message + + \note Common dialog boxes are application modal. No more than one common dialog box + can be open at any time. Request for additional dialog boxes are ignored. + \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] defstr defines the default returned string if no text is entered - \return the user string input if OK was pushed, NULL if Cancel was pushed + \return the user string input if OK was pushed, NULL if Cancel was pushed or another dialog box was still open */ const char* fl_input(const char *fmt, const char *defstr, ...) { fl_beep(FL_BEEP_QUESTION); @@ -395,9 +420,13 @@ const char* fl_input(const char *fmt, const char *defstr, ...) { Like fl_input() except the input text is not shown, '*' characters are displayed instead. + + \note Common dialog boxes are application modal. No more than one common dialog box + can be open at any time. Request for additional dialog boxes are ignored. + \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] defstr defines the default returned string if no text is entered - \return the user string input if OK was pushed, NULL if Cancel was pushed + \return the user string input if OK was pushed, NULL if Cancel was pushed or aother dialog box was still open */ const char *fl_password(const char *fmt, const char *defstr, ...) { fl_beep(FL_BEEP_PASSWORD); diff --git a/src/fl_shortcut.cxx b/src/fl_shortcut.cxx index 050d454b2..9bf18cca9 100644 --- a/src/fl_shortcut.cxx +++ b/src/fl_shortcut.cxx @@ -169,15 +169,32 @@ static Keyname table[] = { /** Get a human-readable string from a shortcut value. + Unparse a shortcut value as used by Fl_Button or Fl_Menu_Item into a human-readable string like "Alt+N". This only works if the shortcut is a character key or a numbered function key. If the shortcut is zero then an empty string is returned. The return value points at a static buffer that is overwritten with each call. + + \param [in] shortcut the integer value containing the ascii charcter or extended keystroke plus modifiers + \return a pointer to a static buffer containing human readable text for the shortcut */ const char* fl_shortcut_label(int shortcut) { + return fl_shortcut_label(shortcut, 0L); +} + +/** + Get a human-readable string from a shortcut value. + + \param [in] shortcut the integer value containing the ascii charcter or extended keystroke plus modifiers + \param [in] eom if this pointer is set, it will receive a pointer to the end of the modifier text + \return a pointer to a static buffer containing human readable text for the shortcut + \see fl_shortcut_label(int shortcut) + */ +const char* fl_shortcut_label(int shortcut, const char **eom) { static char buf[20]; char *p = buf; + if (eom) *eom = p; if (!shortcut) {*p = 0; return buf;} // fix upper case shortcuts int v = shortcut & 0xffff; @@ -202,6 +219,7 @@ const char* fl_shortcut_label(int shortcut) { if (shortcut & FL_SHIFT) {strcpy(p,"Shift+"); p += 6;} if (shortcut & FL_CTRL) {strcpy(p,"Ctrl+"); p += 5;} #endif // __APPLE__ + if (eom) *eom = p; int key = shortcut & 0xFFFF; #if defined(WIN32) || defined(__APPLE__) // if not X if (key >= FL_F && key <= FL_F_Last) { @@ -215,8 +233,14 @@ const char* fl_shortcut_label(int shortcut) { while (a < b) { int c = (a+b)/2; if (table[c].key == key) { - if (p > buf) {strcpy(p,table[c].name); return buf;} - return table[c].name; + if (p > buf) { + strcpy(p,table[c].name); + return buf; + } else { + const char *sp = table[c].name; + if (eom) *eom = sp; + return sp; + } } if (table[c].key < key) a = c+1; else b = c; @@ -238,7 +262,13 @@ const char* fl_shortcut_label(int shortcut) { else if (key > 32 && key < 0x100) q = 0; else q = XKeysymToString(key); if (!q) {*p++ = uchar(toupper(key & 255)); *p = 0; return buf;} - if (p > buf) {strcpy(p,q); return buf;} else return q; + if (p > buf) { + strcpy(p,q); + return buf; + } else { + if (eom) *eom = q; + return q; + } #endif }