diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index bfcac69506..aa3be09e45 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -431,6 +431,12 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, return true; } + if (method_name == "operator |=") { + def._answer_location = "nb_inplace_or"; + def._wrapper_type = WT_inplace_binary_operator; + return true; + } + if (method_name == "__ipow__") { def._answer_location = "nb_inplace_power"; def._wrapper_type = WT_inplace_ternary_operator; diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index 0a140109c7..42490b43da 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -1618,7 +1618,7 @@ handle_key_event(NSEvent *event) { if ([event type] == NSKeyDown) { // Translate it to a unicode character for keystrokes. I would use // interpretKeyEvents and insertText, but that doesn't handle dead keys. - TISInputSourceRef input_source = TISCopyCurrentKeyboardInputSource(); + TISInputSourceRef input_source = TISCopyCurrentKeyboardLayoutInputSource(); CFDataRef layout_data = (CFDataRef)TISGetInputSourceProperty(input_source, kTISPropertyUnicodeKeyLayoutData); const UCKeyboardLayout *layout = (const UCKeyboardLayout *)CFDataGetBytePtr(layout_data); @@ -1827,7 +1827,7 @@ get_keyboard_map() const { const UCKeyboardLayout *layout; // Get the current keyboard layout data. - input_source = TISCopyCurrentKeyboardInputSource(); + input_source = TISCopyCurrentKeyboardLayoutInputSource(); layout_data = (CFDataRef) TISGetInputSourceProperty(input_source, kTISPropertyUnicodeKeyLayoutData); layout = (const UCKeyboardLayout *)CFDataGetBytePtr(layout_data); diff --git a/panda/src/device/ioKitInputDevice.cxx b/panda/src/device/ioKitInputDevice.cxx index da1369932e..8468fd4816 100644 --- a/panda/src/device/ioKitInputDevice.cxx +++ b/panda/src/device/ioKitInputDevice.cxx @@ -22,8 +22,11 @@ #include "mouseButton.h" static void removal_callback(void *ctx, IOReturn result, void *sender) { - IOKitInputDevice *input_device = (IOKitInputDevice *)ctx; + // We need to hold a reference to this because it may otherwise be destroyed + // during the call to on_remove(). + PT(IOKitInputDevice) input_device = (IOKitInputDevice *)ctx; nassertv(input_device != nullptr); + nassertv(input_device->test_ref_count_integrity()); input_device->on_remove(); } diff --git a/panda/src/putil/sparseArray.cxx b/panda/src/putil/sparseArray.cxx index 6373e53039..5404728aa1 100644 --- a/panda/src/putil/sparseArray.cxx +++ b/panda/src/putil/sparseArray.cxx @@ -262,8 +262,8 @@ compare_to(const SparseArray &other) const { return -1; } - --ai; - --bi; + ++ai; + ++bi; } if (ai != _subranges.rend()) { @@ -440,9 +440,9 @@ do_remove_range(int begin, int end) { if (si == _subranges.end()) { if (!_subranges.empty()) { si = _subranges.begin() + _subranges.size() - 1; - if ((*si)._end >= begin) { + if ((*si)._end > begin) { // The new range shortens the last element of the array on the right. - end = std::min(end, (*si)._begin); + end = std::max(begin, (*si)._begin); (*si)._end = end; // It might also shorten it on the left; fall through. } else { @@ -462,10 +462,10 @@ do_remove_range(int begin, int end) { if (si != _subranges.begin()) { Subranges::iterator si2 = si; --si2; - if ((*si2)._end >= begin) { + if ((*si2)._end > begin) { // The new range shortens an element within the array on the right // (but does not intersect the next element). - end = std::min(end, (*si2)._begin); + end = std::max(begin, (*si2)._begin); (*si2)._end = end; // It might also shorten it on the left; fall through. si = si2; @@ -488,7 +488,7 @@ do_remove_range(int begin, int end) { } // Check if the new range removes any elements to the left. - while (begin <= (*si)._begin) { + while (begin <= (*si)._begin || (*si)._begin >= (*si)._end) { if (si == _subranges.begin()) { _subranges.erase(si); return; @@ -500,6 +500,7 @@ do_remove_range(int begin, int end) { } (*si)._end = std::min((*si)._end, begin); + nassertv((*si)._end > (*si)._begin); } /** diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index 5599959cdb..0a5d969bdf 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -589,7 +589,13 @@ set_properties_now(WindowProperties &properties) { // OK, first figure out which CRTC the window is on. It may be on more // than one, actually, so grab a point in the center in order to figure // out which one it's more-or-less mostly on. - LPoint2i center = _properties.get_origin() + _properties.get_size() / 2; + LPoint2i center(0, 0); + if (_properties.has_origin()) { + center = _properties.get_origin(); + if (_properties.has_size()) { + center += _properties.get_size() / 2; + } + } int x, y, width, height; x11_pipe->find_fullscreen_crtc(center, x, y, width, height); @@ -628,7 +634,7 @@ set_properties_now(WindowProperties &properties) { // We may need to change the screen resolution. The code below is // suboptimal; in the future, we probably want to only touch the CRTC // that the window is on. - XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, _xwindow); + XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, _xwindow ? _xwindow : x11_pipe->get_root()); SizeID old_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation); SizeID new_size_id = (SizeID) -1; int num_sizes = 0; @@ -1010,34 +1016,6 @@ open_window() { // Make sure we are not making X11 calls from other threads. LightReMutexHolder holder(x11GraphicsPipe::_x_mutex); - if (_properties.get_fullscreen() && x11_pipe->_have_xrandr) { - XRRScreenConfiguration* conf = _XRRGetScreenInfo(_display, x11_pipe->get_root()); - if (_orig_size_id == (SizeID) -1) { - _orig_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation); - } - int num_sizes, new_size_id = -1; - XRRScreenSize *xrrs; - xrrs = x11_pipe->_XRRSizes(_display, 0, &num_sizes); - for (int i = 0; i < num_sizes; ++i) { - if (xrrs[i].width == _properties.get_x_size() && - xrrs[i].height == _properties.get_y_size()) { - new_size_id = i; - } - } - if (new_size_id == -1) { - x11display_cat.error() - << "Videocard has no supported display resolutions at specified res (" - << _properties.get_x_size() << " x " << _properties.get_y_size() <<")\n"; - _orig_size_id = -1; - return false; - } - if (new_size_id != _orig_size_id) { - _XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime); - } else { - _orig_size_id = -1; - } - } - X11_Window parent_window = x11_pipe->get_root(); WindowHandle *window_handle = _properties.get_parent_window(); if (window_handle != nullptr) { diff --git a/tests/putil/test_sparsearray.py b/tests/putil/test_sparsearray.py new file mode 100644 index 0000000000..b7767d6e8a --- /dev/null +++ b/tests/putil/test_sparsearray.py @@ -0,0 +1,234 @@ +from panda3d import core + + +def test_sparse_array_set_bit_to(): + """Tests SparseArray behavior for set_bit_to().""" + + s = core.SparseArray() + s.set_bit_to(5, True) + assert s.get_bit(5) + + s = core.SparseArray.all_on() + s.set_bit_to(5, False) + assert not s.get_bit(5) + + +def test_sparse_array_clear(): + """Tests SparseArray behavior for clear().""" + + s = core.SparseArray.all_on() + s.clear() + assert s.is_zero() + assert not s.is_inverse() + assert s.get_num_subranges() == 0 + assert s.get_num_on_bits() == 0 + assert s.get_num_bits() == 0 + + s = core.SparseArray() + s.set_range(5, 10) + s.clear() + assert s.is_zero() + assert not s.is_inverse() + assert s.get_num_subranges() == 0 + assert s.get_num_on_bits() == 0 + assert s.get_num_bits() == 0 + + +def test_sparse_array_clear_range(): + # Not using parametrize because there are too many values for that. + for mask in range(0x7f): + for begin in range(8): + for size in range(8): + b = core.BitArray(mask) + s = core.SparseArray(b) + + s.clear_range(begin, size) + b.clear_range(begin, size) + + assert core.BitArray(s) == b + assert s == core.SparseArray(b) + + +def test_sparse_array_set_clear_ranges(): + """Tests SparseArray behavior for setting and clearing ranges.""" + + # test clear_range with single overlapping on-range + # (clear_range extends beyond highest on-bit) + s = core.SparseArray() + s.set_range(2, 3) + s.clear_range(3, 3) + assert s.get_bit(2) + assert not s.get_bit(3) + + # same as above, using set_range_to + s = core.SparseArray() + s.set_range_to(True, 2, 3) + s.set_range_to(False, 3, 3) + assert s.get_bit(2) + assert not s.get_bit(3) + + # test clear_range using off-range which overlaps two on-ranges + # (lowest off-bit in lowest on-range, highest off-bit in highest on-range) + s = core.SparseArray() + s.set_range(2, 3) + s.set_range(7, 3) + s.clear_range(3, 6) + assert s.get_bit(2) + assert not s.get_bit(3) + assert not s.get_bit(8) + assert s.get_bit(9) + + # same as above, using set_range_to + s = core.SparseArray() + s.set_range_to(True, 2, 3) + s.set_range_to(True, 7, 3) + s.set_range_to(False, 3, 6) + assert s.get_bit(2) + assert not s.get_bit(3) + assert not s.get_bit(8) + assert s.get_bit(9) + + +def test_sparse_array_set_range(): + """Tests SparseArray behavior for set_range().""" + + # test set_range with single overlapping off-range + # (set_range extends beyond highest off-bit) + s = core.SparseArray.all_on() + s.clear_range(2, 3) + s.set_range(3, 3) + assert not s.get_bit(2) + assert s.get_bit(3) + + # same as above, using set_range_to + s = core.SparseArray.all_on() + s.set_range_to(False, 2, 3) + s.set_range_to(True, 3, 3) + assert not s.get_bit(2) + assert s.get_bit(3) + + # test set_range using on-range which overlaps two off-ranges + # (lowest on-bit in lowest off-range, highest on-bit in highest off-range) + s = core.SparseArray.all_on() + s.clear_range(2, 3) + s.clear_range(7, 3) + s.set_range(3, 6) + assert not s.get_bit(2) + assert s.get_bit(3) + assert s.get_bit(8) + assert not s.get_bit(9) + + # same as above, using set_range_to + s = core.SparseArray.all_on() + s.set_range_to(False, 2, 3) + s.set_range_to(False, 7, 3) + s.set_range_to(True, 3, 6) + assert not s.get_bit(2) + assert s.get_bit(3) + assert s.get_bit(8) + assert not s.get_bit(9) + + +def test_sparse_array_bits_in_common(): + """Tests SparseArray behavior for has_bits_in_common().""" + + s = core.SparseArray() + t = core.SparseArray() + s.set_range(2, 4) + t.set_range(5, 4) + assert s.has_bits_in_common(t) + + s = core.SparseArray() + t = core.SparseArray() + s.set_range(2, 4) + t.set_range(6, 4) + assert not s.has_bits_in_common(t) + + +def test_sparse_array_operations(): + """Tests SparseArray behavior for various operations.""" + + # test bitshift to left + s = core.SparseArray() + s.set_bit(2) + t = s << 2 + assert t.get_bit(4) + assert not t.get_bit(2) + + # test bitshift to right + s = core.SparseArray() + s.set_bit(4) + t = s >> 2 + assert t.get_bit(2) + assert not t.get_bit(4) + + # test bitwise AND + s = core.SparseArray() + t = core.SparseArray() + s.set_bit(2) + s.set_bit(3) + t.set_bit(1) + t.set_bit(3) + u = s & t + assert not u.get_bit(0) + assert not u.get_bit(1) + assert not u.get_bit(2) + assert u.get_bit(3) + + # test bitwise OR + s = core.SparseArray() + t = core.SparseArray() + s.set_bit(2) + s.set_bit(3) + t.set_bit(1) + t.set_bit(3) + u = s | t + assert not u.get_bit(0) + assert u.get_bit(1) + assert u.get_bit(2) + assert u.get_bit(3) + + # test bitwise XOR + s = core.SparseArray() + t = core.SparseArray() + s.set_bit(2) + s.set_bit(3) + t.set_bit(1) + t.set_bit(3) + u = s ^ t + assert not u.get_bit(0) + assert u.get_bit(1) + assert u.get_bit(2) + assert not u.get_bit(3) + + +def test_sparse_array_augm_assignment(): + """Tests SparseArray behavior for augmented assignments.""" + + # test in-place bitshift to left + s = t = core.SparseArray() + t <<= 2 + assert s is t + + # test in-place bitshift to right + s = t = core.SparseArray() + t >>= 2 + assert s is t + + # test in-place bitwise AND + s = t = core.SparseArray() + u = core.SparseArray() + t &= u + assert s is t + + # test in-place bitwise OR + s = t = core.SparseArray() + u = core.SparseArray() + t |= u + assert s is t + + # test in-place bitwise XOR + s = t = core.SparseArray() + u = core.SparseArray() + t ^= u + assert s is t