*/
class FL_EXPORT Fl_Widget {
friend class Fl_Group;
- friend class Fl_X;
Fl_Group* parent_;
Fl_Callback* callback_;
public:
/** Localizable text for the "About xxx" application menu item */
static const char *about;
+ /** Copyright notice for the default about dialog. Will use the information
+ from the bundle if set to an empty string. */
+ static const char *copyright;
/** Localizable text for the "Print Front Window" application menu item.
This menu item won't be displayed if Fl_Mac_App_Menu::print
is set to an empty string.
int wait_for_expose;
HDC private_dc; // used for OpenGL
HCURSOR cursor;
+ int custom_cursor;
HDC saved_hdc; // saves the handle of the DC currently loaded
// static variables, static functions and member functions
static Fl_X* first;
//
#if defined(__APPLE__) || defined(FL_DOXYGEN)
const char *Fl_Mac_App_Menu::about = "About ";
+const char *Fl_Mac_App_Menu::copyright = NULL;
const char *Fl_Mac_App_Menu::print = "Print Front Window";
const char *Fl_Mac_App_Menu::services = "Services";
const char *Fl_Mac_App_Menu::hide = "Hide ";
- (void)rightMouseDragged:(NSEvent *)theEvent;
- (void)otherMouseDragged:(NSEvent *)theEvent;
- (void)scrollWheel:(NSEvent *)theEvent;
++ (NSString *)keyTranslate:(UInt16)keyCode withModifierFlags:(UInt32)modifierFlags;
- (BOOL)handleKeyDown:(NSEvent *)theEvent;
- (void)keyDown:(NSEvent *)theEvent;
- (void)keyUp:(NSEvent *)theEvent;
- (void)scrollWheel:(NSEvent *)theEvent {
cocoaMouseWheelHandler(theEvent);
}
++ (NSString *)keyTranslate:(UInt16)keyCode withModifierFlags:(UInt32)modifierFlags {
+ const UCKeyboardLayout *layout;
+ OSStatus err;
+
+ layout = NULL;
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
+ TISInputSourceRef keyboard;
+ CFDataRef uchr;
+
+ keyboard = TISCopyCurrentKeyboardInputSource();
+ uchr = (CFDataRef)TISGetInputSourceProperty(keyboard,
+ kTISPropertyUnicodeKeyLayoutData);
+ if (uchr == NULL)
+ return nil;
+
+ layout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
+#else
+ KeyboardLayoutRef old_layout;
+ int kind;
+
+ err = KLGetCurrentKeyboardLayout(&old_layout);
+ if (err != noErr)
+ return nil;
+
+ err = KLGetKeyboardLayoutProperty(old_layout, kKLKind,
+ (const void**)&kind);
+ if (err != noErr)
+ return nil;
+
+ // Old, crufty layout format?
+ if (kind == kKLKCHRKind) {
+ void *kchr_layout;
+
+ UInt32 chars, state;
+ char buf[3];
+
+ unichar result[16];
+ ByteCount in_len, out_len;
+
+ err = KLGetKeyboardLayoutProperty(old_layout, kKLKCHRData,
+ (const void**)&kchr_layout);
+ if (err != noErr)
+ return nil;
+
+ state = 0;
+
+ keyCode &= 0x7f;
+ modifierFlags &= 0xff00;
+
+ chars = KeyTranslate(kchr_layout, keyCode | modifierFlags, &state);
+
+ buf[0] = (chars >> 16) & 0xff;
+ buf[1] = chars & 0xff;
+ buf[2] = '\0';
+
+ if (buf[0] == '\0') {
+ buf[0] = buf[1];
+ buf[1] = '\0';
+ }
+
+ // The data is now in some layout specific encoding. Need to convert
+ // this to unicode.
+
+ ScriptCode script;
+ TextEncoding encoding;
+ TECObjectRef converter;
+
+ script = (ScriptCode)GetScriptManagerVariable(smKeyScript);
+
+ err = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL,
+ &encoding);
+ if (err != noErr)
+ return nil;
+
+ err = TECCreateConverter(&converter, encoding, kTextEncodingUnicodeV4_0);
+ if (err != noErr)
+ return nil;
+
+ in_len = strlen(buf);
+ out_len = sizeof(result);
+
+ err = TECConvertText(converter, (ConstTextPtr)buf, in_len, &in_len,
+ (TextPtr)result, out_len, &out_len);
+
+ TECDisposeConverter(converter);
+
+ if (err != noErr)
+ return nil;
+
+ return [NSString stringWithCharacters:result
+ length:(out_len / sizeof(unichar))];
+ }
+
+ if ((kind != kKLKCHRuchrKind) && (kind != kKLuchrKind))
+ return nil;
+
+ err = KLGetKeyboardLayoutProperty(old_layout, kKLuchrData,
+ (const void**)&layout);
+ if (err != noErr)
+ return nil;
+#endif
+
+ if (layout == NULL)
+ return nil;
+
+ UInt32 dead_state;
+ UniCharCount max_len, actual_len;
+ UniChar string[255];
+
+ dead_state = 0;
+ max_len = sizeof(string)/sizeof(*string);
+
+ modifierFlags = (modifierFlags >> 8) & 0xff;
+
+ err = UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierFlags,
+ LMGetKbdType(), 0, &dead_state, max_len, &actual_len,
+ string);
+ if (err != noErr)
+ return nil;
+
+ return [NSString stringWithCharacters:string length:actual_len];
+}
- (BOOL)handleKeyDown:(NSEvent *)theEvent {
//NSLog(@"handleKeyDown");
fl_lock_function();
break;
}
}
- // Don't send cmd-<key> to interpretKeyEvents because it beeps.
- if (!no_text_key && !(Fl::e_state & FL_META) ) {
+ if (!no_text_key) {
// The simple keyboard model will ignore insertText, so we need to grab
// the symbol directly from the event. Note that we still use setMarkedText.
- if (use_simple_keyboard)
- [FLView prepareEtext:[theEvent charactersIgnoringModifiers]];
+ if (use_simple_keyboard) {
+ NSString *simple_chars;
+ UInt32 modifiers;
+
+ // We want a "normal" symbol out of the event, which basically means
+ // we only respect the shift and alt/altgr modifiers. Cocoa can help
+ // us if we only wanted shift, but as we also want alt/altgr, we'll
+ // have to do some lookup ourselves. This matches our behaviour on
+ // other platforms.
+
+ modifiers = 0;
+ if ([theEvent modifierFlags] & NSAlphaShiftKeyMask)
+ modifiers |= alphaLock;
+ if ([theEvent modifierFlags] & NSShiftKeyMask)
+ modifiers |= shiftKey;
+ if ([theEvent modifierFlags] & NSAlternateKeyMask)
+ modifiers |= optionKey;
+
+ simple_chars = [FLView keyTranslate:[theEvent keyCode]
+ withModifierFlags:modifiers];
+ if (simple_chars == nil) {
+ // Something went wrong. Fall back to what Cocoa gave us...
+ simple_chars = [theEvent charactersIgnoringModifiers];
+ }
+
+ [FLView prepareEtext:simple_chars];
+ }
// Then we can let the OS have a stab at it and see if it thinks it
// should result in some text
- NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
- in_key_event = true;
- [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
- in_key_event = false;
+
+ // Don't send cmd-<key> to interpretKeyEvents because it beeps.
+ if (!(Fl::e_state & FL_META)) {
+ NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
+ in_key_event = true;
+ [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+ in_key_event = false;
+ }
}
//NSLog(@"to text=%@ l=%d", [NSString stringWithUTF8String:Fl::e_text], Fl::e_length);
int handled = Fl::handle(FL_KEYDOWN, window);
@implementation FLaboutItemTarget
- (void)showPanel
{
- NSDictionary *options;
- options = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSString stringWithFormat:@" GUI with FLTK %d.%d", FL_MAJOR_VERSION,
- FL_MINOR_VERSION ], @"Copyright",
- nil];
- [NSApp orderFrontStandardAboutPanelWithOptions:options];
+ if ((Fl_Mac_App_Menu::copyright == NULL) ||
+ (strlen(Fl_Mac_App_Menu::copyright) > 0)) {
+ NSString *copyright;
+
+ if (Fl_Mac_App_Menu::copyright == NULL)
+ copyright = [NSString stringWithFormat:@" GUI with FLTK %d.%d",
+ FL_MAJOR_VERSION, FL_MINOR_VERSION ];
+ else
+ copyright = [NSString stringWithUTF8String:Fl_Mac_App_Menu::copyright];
+
+ NSDictionary *options;
+ options = [NSDictionary dictionaryWithObjectsAndKeys:
+ copyright, @"Copyright",
+ nil];
+
+ [NSApp orderFrontStandardAboutPanelWithOptions:options];
+ } else {
+ [NSApp orderFrontStandardAboutPanelWithOptions:nil];
+ }
}
//#include <FL/Fl_PostScript.H>
- (void)printPanel
// Pressing Ctrl wreaks havoc with the symbol lookup, so turn that off.
// But AltGr shows up as Ctrl+Alt in Windows, so keep Ctrl if Alt is
// active.
- if (!(keystate[VK_MENU] & (1<<31)))
+ if (!(keystate[VK_MENU] & 0x80))
keystate[VK_CONTROL] = keystate[VK_LCONTROL] = keystate[VK_RCONTROL] = 0;
// We cannot inspect or modify Windows' internal state of the keyboard
x->region = 0;
x->private_dc = 0;
x->cursor = LoadCursor(NULL, IDC_ARROW);
+ x->custom_cursor = 0;
if (!fl_codepage) fl_get_codepage();
WCHAR *lab = NULL;
int Fl_X::set_cursor(Fl_Cursor c) {
LPSTR n;
+ HCURSOR new_cursor;
if (c == FL_CURSOR_NONE)
- cursor = NULL;
+ new_cursor = NULL;
else {
switch (c) {
case FL_CURSOR_ARROW: n = IDC_ARROW; break;
return 0;
}
- cursor = LoadCursor(NULL, n);
- if (cursor == NULL)
+ new_cursor = LoadCursor(NULL, n);
+ if (new_cursor == NULL)
return 0;
}
+ if ((cursor != NULL) && custom_cursor)
+ DestroyIcon(cursor);
+
+ cursor = new_cursor;
+ custom_cursor = 0;
+
SetCursor(cursor);
return 1;
BITMAPV5HEADER bi;
HBITMAP bitmap, mask;
DWORD *bits;
+ HCURSOR new_cursor;
if ((hotx < 0) || (hotx >= image->w()))
return 0;
bi.bV5Size = sizeof(BITMAPV5HEADER);
bi.bV5Width = image->w();
- bi.bV5Height = image->h();
+ bi.bV5Height = -image->h(); // Negative for top-down
bi.bV5Planes = 1;
bi.bV5BitCount = 32;
bi.bV5Compression = BI_BITFIELDS;
bitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
ReleaseDC(NULL, hdc);
+ if (bits == NULL)
+ return 0;
+
const uchar *i = (const uchar*)*image->data();
for (int y = 0;y < image->h();y++) {
for (int x = 0;x < image->w();x++) {
// A mask bitmap is still needed even though it isn't used
mask = CreateBitmap(image->w(),image->h(),1,1,NULL);
+ if (mask == NULL) {
+ DeleteObject(bitmap);
+ return 0;
+ }
ICONINFO ii;
ii.hbmMask = mask;
ii.hbmColor = bitmap;
- cursor = CreateIconIndirect(&ii);
+ new_cursor = CreateIconIndirect(&ii);
DeleteObject(bitmap);
DeleteObject(mask);
+ if (new_cursor == NULL)
+ return 0;
+
+ if ((cursor != NULL) && custom_cursor)
+ DestroyIcon(cursor);
+
+ cursor = new_cursor;
+ custom_cursor = 1;
+
SetCursor(cursor);
return 1;
if ((chars_per_pixel < 1) || (chars_per_pixel > 2))
return 0;
- uchar (*colors)[4] = new uchar [1<<(chars_per_pixel*8)][4];
+ uchar colors[1<<(chars_per_pixel*8)][4];
#ifdef WIN32
color_count = 0;
}
}
- delete [] colors;
return 1;
}
if (!fl_measure_pixmap(cdata, w, h))
return 0;
- uchar *buffer = new uchar[w*h*4];
+ uchar buffer[w*h*4];
- if (!fl_convert_pixmap(cdata, buffer, bg)) {
- delete buffer;
+ if (!fl_convert_pixmap(cdata, buffer, bg))
return 0;
- }
// FIXME: Hack until fl_draw_image() supports alpha properly
#ifdef __APPLE_QUARTZ__
}
#endif
- delete buffer;
return 1;
}
#include <FL/x.H>
#include <config.h>
+#define MAX_SCREENS 16
// Number of screens returned by multi monitor aware API; -1 before init
static int num_screens = -1;
if (fl_edm) {
// We do have EnumDisplayMonitors, so lets find out how many monitors...
- num_screens = GetSystemMetrics(SM_CMONITORS);
+ //num_screens = GetSystemMetrics(SM_CMONITORS);
// if (num_screens > 1) {
// If there is more than 1 monitor, enumerate them...
}
num_screens = count;
}
-#elif HAVE_XINERAMA
-# include <X11/extensions/Xinerama.h>
+#else
-// Screen data...
-static XineramaScreenInfo *screens;
-static float dpi[16][2];
+#if HAVE_XINERAMA
+# include <X11/extensions/Xinerama.h>
+#endif
+typedef struct {
+ short x_org;
+ short y_org;
+ short width;
+ short height;
+} FLScreenInfo;
+static FLScreenInfo screens[MAX_SCREENS];
+static float dpi[MAX_SCREENS][2];
static void screen_init() {
if (!fl_display) fl_open_display();
+ // FIXME: Rewrite using randr instead
+#if HAVE_XINERAMA
if (XineramaIsActive(fl_display)) {
- screens = XineramaQueryScreens(fl_display, &num_screens);
- int i;
- // Xlib and Xinerama may disagree on the screen count. Sigh...
- // Use the minimum of the reported counts.
- // Use the previous screen's info for non-existent ones.
- int sc = ScreenCount(fl_display); // Xlib screen count
- for (i=0; i<num_screens; i++) {
- int mm = (i < sc) ? DisplayWidthMM(fl_display, i) : 0;
- dpi[i][0] = mm ? screens[i].width*25.4f/mm : (i > 0) ? dpi[i-1][0] : 0.0f;
- mm = (i < sc) ? DisplayHeightMM(fl_display, i) : 0;
- dpi[i][1] = mm ? screens[i].height*25.4f/mm : (i > 0) ? dpi[i-1][1] : 0.0f;
+ static XineramaScreenInfo *xsi = XineramaQueryScreens(fl_display, &num_screens);
+ if (num_screens > MAX_SCREENS) num_screens = MAX_SCREENS;
+
+ /* There's no way to use different DPI for different Xinerama
+ screens. */
+ for (int i=0; i<num_screens; i++) {
+ screens[i].x_org = xsi[i].x_org;
+ screens[i].y_org = xsi[i].y_org;
+ screens[i].width = xsi[i].width;
+ screens[i].height = xsi[i].height;
+
+ int mm = DisplayWidthMM(fl_display, fl_screen);
+ dpi[i][0] = mm ? screens[i].width*25.4f/mm : 0.0f;
+ mm = DisplayHeightMM(fl_display, fl_screen);
+ dpi[i][1] = mm ? screens[i].height*25.4f/mm : 0.0f;
+ }
+ } else
+#endif
+ { // ! XineramaIsActive()
+ num_screens = ScreenCount(fl_display);
+ if (num_screens > MAX_SCREENS) num_screens = MAX_SCREENS;
+
+ for (int i=0; i<num_screens; i++) {
+ screens[i].x_org = 0;
+ screens[i].y_org = 0;
+ screens[i].width = DisplayWidth(fl_display, i);
+ screens[i].height = DisplayHeight(fl_display, i);
+
+ int mm = DisplayWidthMM(fl_display, i);
+ dpi[i][0] = mm ? DisplayWidth(fl_display, i)*25.4f/mm : 0.0f;
+ mm = DisplayHeightMM(fl_display, i);
+ dpi[i][1] = mm ? DisplayHeight(fl_display, i)*25.4f/mm : 0.0f;
}
- } else { // ! XineramaIsActive()
- num_screens = 1;
- int mm = DisplayWidthMM(fl_display, fl_screen);
- dpi[0][0] = mm ? Fl::w()*25.4f/mm : 0.0f;
- mm = DisplayHeightMM(fl_display, fl_screen);
- dpi[0][1] = mm ? Fl::h()*25.4f/mm : dpi[0][0];
}
}
-#else
-static float dpi[2];
-static void screen_init() {
- num_screens = 1;
- if (!fl_display) fl_open_display();
- int mm = DisplayWidthMM(fl_display, fl_screen);
- dpi[0] = mm ? Fl::w()*25.4f/mm : 0.0f;
- mm = DisplayHeightMM(fl_display, fl_screen);
- dpi[1] = mm ? Fl::h()*25.4f/mm : dpi[0];
-}
+
#endif // WIN32
H = Fl::h();
}
#else
-#if HAVE_XINERAMA
- if (num_screens > 0 && screens) {
+ if (num_screens > 0) {
X = screens[n].x_org;
Y = screens[n].y_org;
W = screens[n].width;
H = screens[n].height;
- } else
-#endif // HAVE_XINERAMA
- {
- /* Fallback if something is broken (or no Xinerama)... */
- X = 0;
- Y = 0;
- W = DisplayWidth(fl_display, fl_screen);
- H = DisplayHeight(fl_display, fl_screen);
}
#endif // WIN32
}
h = dpi_h[n];
v = dpi_v[n];
}
-#elif HAVE_XINERAMA
+#else
if (n >= 0 && n < num_screens) {
h = dpi[n][0];
v = dpi[n][1];
}
-#else
- if (n >= 0 && n < num_screens) {
- h = dpi[0];
- v = dpi[1];
- }
#endif // WIN32
}