diff options
Diffstat (limited to 'platform/osx/os_osx.mm')
-rw-r--r-- | platform/osx/os_osx.mm | 160 |
1 files changed, 129 insertions, 31 deletions
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index fbefd41bb7..bde0b4e898 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -541,7 +541,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; } - (void)cursorUpdate:(NSEvent *)event { - //setModeCursor(window, window->cursorMode); + OS::CursorShape p_shape = OS_OSX::singleton->cursor_shape; + OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX; + OS_OSX::singleton->set_cursor_shape(p_shape); } static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { @@ -656,11 +658,12 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { return; if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED) OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); - if (OS_OSX::singleton->input) { + if (OS_OSX::singleton->input) OS_OSX::singleton->input->set_mouse_in_window(true); - OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX; - OS_OSX::singleton->set_cursor_shape(OS::CURSOR_ARROW); - } + + OS::CursorShape p_shape = OS_OSX::singleton->cursor_shape; + OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX; + OS_OSX::singleton->set_cursor_shape(p_shape); } - (void)magnifyWithEvent:(NSEvent *)event { @@ -847,16 +850,16 @@ struct _KeyCodeMap { static const _KeyCodeMap _keycodes[55] = { { '`', KEY_QUOTELEFT }, { '~', KEY_ASCIITILDE }, - { '0', KEY_KP_0 }, - { '1', KEY_KP_1 }, - { '2', KEY_KP_2 }, - { '3', KEY_KP_3 }, - { '4', KEY_KP_4 }, - { '5', KEY_KP_5 }, - { '6', KEY_KP_6 }, - { '7', KEY_KP_7 }, - { '8', KEY_KP_8 }, - { '9', KEY_KP_9 }, + { '0', KEY_0 }, + { '1', KEY_1 }, + { '2', KEY_2 }, + { '3', KEY_3 }, + { '4', KEY_4 }, + { '5', KEY_5 }, + { '6', KEY_6 }, + { '7', KEY_7 }, + { '8', KEY_8 }, + { '9', KEY_9 }, { '-', KEY_MINUS }, { '_', KEY_UNDERSCORE }, { '=', KEY_EQUAL }, @@ -1330,6 +1333,9 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a restore_rect = Rect2(get_window_position(), get_window_size()); + if (p_desired.layered_splash) { + set_window_per_pixel_transparency_enabled(true); + } return OK; } @@ -1510,39 +1516,78 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) { void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { if (p_cursor.is_valid()) { Ref<Texture> texture = p_cursor; - Ref<Image> image = texture->get_data(); + Ref<AtlasTexture> atlas_texture = p_cursor; + Ref<Image> image; + Size2 texture_size; + Rect2 atlas_rect; - ERR_FAIL_COND(texture->get_width() > 256 || texture->get_height() > 256); + if (texture.is_valid()) { + image = texture->get_data(); + } + + if (!image.is_valid() && atlas_texture.is_valid()) { + texture = atlas_texture->get_atlas(); + + atlas_rect.size.width = texture->get_width(); + atlas_rect.size.height = texture->get_height(); + atlas_rect.position.x = atlas_texture->get_region().position.x; + atlas_rect.position.y = atlas_texture->get_region().position.y; + + texture_size.width = atlas_texture->get_region().size.x; + texture_size.height = atlas_texture->get_region().size.y; + } else if (image.is_valid()) { + texture_size.width = texture->get_width(); + texture_size.height = texture->get_height(); + } + + ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); + + image = texture->get_data(); NSBitmapImageRep *imgrep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:image->get_width() - pixelsHigh:image->get_height() + pixelsWide:int(texture_size.width) + pixelsHigh:int(texture_size.height) bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:image->get_width() * 4 + bytesPerRow:int(texture_size.width) * 4 bitsPerPixel:32] autorelease]; ERR_FAIL_COND(imgrep == nil); uint8_t *pixels = [imgrep bitmapData]; - int len = image->get_width() * image->get_height(); + int len = int(texture_size.width * texture_size.height); PoolVector<uint8_t> data = image->get_data(); PoolVector<uint8_t>::Read r = data.read(); + image->lock(); + /* Premultiply the alpha channel */ for (int i = 0; i < len; i++) { - uint8_t alpha = r[i * 4 + 3]; - pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255); - pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255); - pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255); + int row_index = floor(i / texture_size.width) + atlas_rect.position.y; + int column_index = (i % int(texture_size.width)) + atlas_rect.position.x; + + if (atlas_texture.is_valid()) { + column_index = MIN(column_index, atlas_rect.size.width - 1); + row_index = MIN(row_index, atlas_rect.size.height - 1); + } + + uint32_t color = image->get_pixel(column_index, row_index).to_argb32(); + + uint8_t alpha = (color >> 24) & 0xFF; + pixels[i * 4 + 0] = ((color >> 16) & 0xFF) * alpha / 255; + pixels[i * 4 + 1] = ((color >> 8) & 0xFF) * alpha / 255; + pixels[i * 4 + 2] = ((color)&0xFF) * alpha / 255; pixels[i * 4 + 3] = alpha; } - NSImage *nsimage = [[[NSImage alloc] initWithSize:NSMakeSize(image->get_width(), image->get_height())] autorelease]; + image->unlock(); + + NSImage *nsimage = [[[NSImage alloc] initWithSize:NSMakeSize(texture_size.width, texture_size.height)] autorelease]; [nsimage addRepresentation:imgrep]; NSCursor *cursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSMakePoint(p_hotspot.x, p_hotspot.y)]; @@ -1552,6 +1597,11 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c if (p_shape == CURSOR_ARROW) { [cursor set]; } + } else { + // Reset to default system cursor + cursors[p_shape] = NULL; + cursor_shape = CURSOR_MAX; + set_cursor_shape(p_shape); } } @@ -2042,6 +2092,8 @@ void OS_OSX::set_window_size(const Size2 p_size) { void OS_OSX::set_window_fullscreen(bool p_enabled) { if (zoomed != p_enabled) { + if (layered_window) + set_window_per_pixel_transparency_enabled(false); [window_object toggleFullScreen:nil]; } zoomed = p_enabled; @@ -2123,6 +2175,39 @@ void OS_OSX::request_attention() { [NSApp requestUserAttention:NSCriticalRequest]; } +bool OS_OSX::get_window_per_pixel_transparency_enabled() const { + + if (!is_layered_allowed()) return false; + return layered_window; +} + +void OS_OSX::set_window_per_pixel_transparency_enabled(bool p_enabled) { + + if (!is_layered_allowed()) return; + if (layered_window != p_enabled) { + if (p_enabled) { + set_borderless_window(true); + GLint opacity = 0; + [window_object setBackgroundColor:[NSColor clearColor]]; + [window_object setOpaque:NO]; + [window_object setHasShadow:NO]; + [context setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity]; + layered_window = true; + } else { + GLint opacity = 1; + [window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]]; + [window_object setOpaque:YES]; + [window_object setHasShadow:YES]; + [context setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity]; + layered_window = false; + } + [context update]; + NSRect frame = [window_object frame]; + [window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES]; + [window_object setFrame:frame display:YES]; + } +} + void OS_OSX::set_borderless_window(bool p_borderless) { // OrderOut prevents a lose focus bug with the window @@ -2131,6 +2216,9 @@ void OS_OSX::set_borderless_window(bool p_borderless) { if (p_borderless) { [window_object setStyleMask:NSWindowStyleMaskBorderless]; } else { + if (layered_window) + set_window_per_pixel_transparency_enabled(false); + [window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable]; // Force update of the window styles @@ -2339,12 +2427,21 @@ void OS_OSX::run() { //int frames=0; //uint64_t frame=0; - while (!force_quit) { + bool quit = false; - process_events(); // get rid of pending events - joypad_osx->process_joypads(); - if (Main::iteration() == true) - break; + while (!force_quit && !quit) { + + @try { + + process_events(); // get rid of pending events + joypad_osx->process_joypads(); + + if (Main::iteration() == true) { + quit = true; + } + } @catch (NSException *exception) { + ERR_PRINTS("NSException: " + String([exception reason].UTF8String)); + } }; main_loop->finish(); @@ -2435,6 +2532,7 @@ OS_OSX::OS_OSX() { im_position = Point2(); im_callback = NULL; im_target = NULL; + layered_window = false; autoreleasePool = [[NSAutoreleasePool alloc] init]; eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); |